Lovable forgot password flow: setup and fixes
A Lovable forgot-password flow has two pages and one dashboard setting. The first page asks Supabase to email a reset link. The second page, where the link lands, lets the user set a new password. The setting is the redirect allow-list: if the reset page’s URL is not on it, the link sends users to the wrong place. Lovable apps use Supabase Auth (through Lovable Cloud or a connected Supabase project), so all three steps follow Supabase’s password reset docs.
Step 1: Request the reset email
On the “Forgot password” page, call resetPasswordForEmail with the address and the URL of your update-password page:
await supabase.auth.resetPasswordForEmail(email, {
redirectTo: `${window.location.origin}/update-password`,
});
Show the same message whether or not the address has an account, for example “If that email is registered, a reset link is on its way.” A different message for unknown emails tells anyone which addresses have accounts.
Step 2: Handle the link on the update-password page
When the user opens the link, Supabase signs them in with a recovery session and fires a PASSWORD_RECOVERY auth event. Show the new-password form, then save it:
supabase.auth.onAuthStateChange((event) => {
if (event === "PASSWORD_RECOVERY") setShowForm(true);
});
await supabase.auth.updateUser({ password: newPassword });
The route must exist in your app’s router and must not sit behind a guard that redirects signed-out users before the session loads.
Step 3: Allow the redirect URL
In the Supabase dashboard, open Authentication → URL Configuration:
- Site URL: your production domain.
- Redirect URLs: the full update-password URL for each domain you use, including the Lovable preview domain and any custom domain.
Supabase rejects a redirectTo that is not on the list and falls back to the Site URL.
Why does the reset link go to localhost?
The Site URL is still set to http://localhost:3000, or redirectTo is missing from the allow-list so Supabase falls back to the Site URL. Set the Site URL to your production domain and add the exact reset URL under Redirect URLs.
Why does the reset link say expired or invalid?
Common causes:
- The link was already used. Some corporate email security scanners open every link in an incoming email, which consumes a one-time link before the user clicks it. Supabase’s docs suggest sending the user to a page with a button that completes the step, or using an emailed code instead of a link.
- The link was opened in a different browser. With the PKCE flow, the reset must complete in the browser that requested it.
- The link is older than its expiry window. Request a new one.
Why are reset emails not arriving?
Supabase’s built-in email service is meant for testing. It has a low hourly sending limit and may only deliver to your project’s team members. For production, configure custom SMTP under Authentication → Emails. See Supabase’s SMTP guide.
Security checks before launch
- Same response for registered and unregistered emails.
- A rate limit on reset requests per address and per IP.
- New passwords checked against breached lists: see leaked password protection in Lovable.
- Other active sessions signed out after a password change, if your app holds sensitive data.
Reset and magic-link mistakes in generated apps are covered in our auth flow patterns. For the rest of a Lovable app’s security settings, see the Lovable security guide.
Reviewed against the Supabase docs on October 9, 2026.
Test your auth flows on the live app
A reset flow that works can still leak which emails have accounts or accept unlimited requests. Scan the deployed app.
14-day free trial · No credit card · Cancel anytime