Lovable auth not working: redirects, email confirmation and lost sessions fixed
Most Lovable auth failures come from four places: your live or custom domain missing from the Redirect URLs list, users stuck unconfirmed, a page guard that runs before the saved session loads, or row level security returning nothing. Check More, then Users, then Settings first, then your auth code and table policies.
Symptom
Login works in the Lovable editor. Then you publish, share the link, and one of these happens:
- Google sign-in fails or drops people back on the login page.
- The confirmation or password reset link sends people to the wrong address.
- Users sign in, refresh the page, and land back on the login screen.
- Sign-in succeeds but the dashboard is empty, with no error.
- Some users can't sign in at all and the app just says something went wrong.
If your app passes Supabase auth errors through, the last one usually carries this code:
Supabase's docs describe it as sign-in being blocked because the user's email address is not confirmed. A close relative is over_email_send_rate_limit, which means too many emails went to one address.
Why it happens
Lovable sets up login quickly, and by default it switches on email and password, Google and Sign in with Lovable. The settings that matter after publishing sit in places most people never open.
Redirect URLs. Every Lovable project has a Site URL (where users land after signing in if nothing else is specified) and a Redirect URLs allowlist of up to 50 addresses. You'll find both under More, then Users, then Settings, then Advanced. On the built-in backend, publishing sets the Site URL to your lovable.app address, and connecting a custom domain adds that domain to the list. There is one catch: if you ever set the Site URL yourself, Lovable leaves it alone. On your own Supabase project, nothing updates automatically. You set these in the Supabase dashboard.
Email confirmation. The Auto-confirm email setting lives under More, then Users, then Settings, then Email. With it off, new users must click a confirmation link before they can sign in. Lovable's docs note two traps: signing in again does not resend the confirmation, and a burst of sign-ups can hit the project's hourly email limit. Until you set up your own email domain, auth emails come from Lovable's default sender.
Sessions lost on refresh. Lovable's docs say users stay signed in until they sign out or are deleted. Each sign-in issues a short-lived access token and a refresh token that renews it. The Supabase client saves the session in the browser's local storage. So when a refresh logs someone out, the session is usually still there. The page checked for a user before the client had loaded it, saw nothing, and redirected to login.
Row level security. When Lovable adds login, it also adds row level security to protect user data. Once security is on, Supabase returns no rows until a policy allows them. A missing or wrong policy doesn't throw an error. It just returns an empty list.
The fix
Work through these in order. The first two are settings, not code.
1. Put every live address in the redirect list
On the built-in backend, open More, then Users, then Settings, then Advanced. Set the Site URL to the address you want people to use, normally your custom domain. Add every address the app is served from to Redirect URLs: the lovable.app address, the custom domain with and without www, and any path your code redirects to.
On your own Supabase project, do the same in the Supabase dashboard under Authentication, on the URL Configuration page. Supabase accepts wildcards there, so https://www.example.com/** covers every path on that domain.
If you use Google sign-in with your own OAuth credentials, also add the redirect URI in Google Cloud Console. In Lovable's managed mode you don't need your own credentials at all.
If your app calls supabase-js directly (search the code for signInWithOAuth and signUp), make sure it sends the current address rather than a hard-coded preview URL:
// Send users back to whichever domain they started on.
const redirectTo = `${window.location.origin}/`;
await supabase.auth.signUp({
email,
password,
options: { emailRedirectTo: redirectTo },
});
await supabase.auth.signInWithOAuth({
provider: "google",
options: { redirectTo },
});That address still has to be in the allowlist. The code chooses where to go, and the list decides whether it's allowed.
2. Unstick unconfirmed users and show a useful message
For testing, Auto-confirm email gets you moving. Lovable's docs say to keep confirmation on for a live app, because without it anyone can sign up with an address they don't own. For a user who is stuck now, either ask them to sign up again with the same email to get a fresh link, or add them yourself under More, then Users, then Add user, then Create new user, which confirms the account automatically.
Then stop showing a generic error. Supabase recommends checking error.code rather than matching message text:
import { isAuthApiError } from "@supabase/supabase-js";
const { error } = await supabase.auth.signInWithPassword({ email, password });
if (error && isAuthApiError(error)) {
if (error.code === "email_not_confirmed") {
setMessage("Check your inbox for the confirmation link, then sign in.");
} else if (error.code === "invalid_credentials") {
setMessage("That email and password don't match.");
} else {
setMessage("Sign-in failed. Please try again.");
}
}3. Wait for the session before guarding pages
The refresh bug is fixed by holding a loading state until the client reports the stored session. Supabase fires an INITIAL_SESSION event with whatever session it found, so a single listener covers both the first load and later changes:
import { createContext, useContext, useEffect, useState, type ReactNode } from "react";
import type { Session } from "@supabase/supabase-js";
import { supabase } from "./supabaseClient"; // use your project's existing client import
type AuthState = { session: Session | null; loading: boolean };
const AuthContext = createContext<AuthState>({ session: null, loading: true });
export function AuthProvider({ children }: { children: ReactNode }) {
const [state, setState] = useState<AuthState>({ session: null, loading: true });
useEffect(() => {
const { data } = supabase.auth.onAuthStateChange((_event, session) => {
setState({ session, loading: false });
});
return () => data.subscription.unsubscribe();
}, []);
return <AuthContext.Provider value={state}>{children}</AuthContext.Provider>;
}
export const useAuth = () => useContext(AuthContext);Your protected page then shows a spinner while loading is true and only redirects when loading has finished and there is no session. While you're in there, check the project creates its Supabase client once. Search for createClient: more than one in the browser code is worth tidying up.
If the problem started right after you upgraded an older project to TanStack Start, Lovable's upgrade guide tells you to confirm sign-in still works afterwards. You can restore the pre-upgrade version from version history while you investigate. Your published site only changes when you publish.
4. Check the policies when signed in but empty
Open More, then Database, then Manage, then Policies. Every table holding user data needs a policy that matches the signed-in user to their rows. The Supabase pattern looks like this:
create policy "Users can read their own projects"
on public.projects
for select
to authenticated
using ( (select auth.uid()) = user_id );Then test with two accounts. Sign in as one, copy a record's URL, sign in as the other and open it. The second user should see nothing.
How to prevent it
- Add each new domain to Redirect URLs before you share it, and recheck after any domain change.
- Test sign-up, confirmation, password reset and Google sign-in on the published domain in a private window, on your phone as well as your laptop.
- Set up your own email domain under More, then Emails on a paid plan, so confirmation emails come from your own domain. A new domain starts with no sending reputation, so set it up well before launch.
- Run the Deep scan from the Security view before launch. It covers authentication and account security, and it doesn't run on its own.
- Add a line to Project settings, then Instructions telling Lovable to keep the auth loading state, so a later prompt doesn't quietly remove it.
- Remember that deleting a user doesn't end an already-issued access token. It works until it expires.
When to get help
If the settings above are right and users still get bounced, the problem is usually spread across several files: a guard in one place, a redirect in another, a policy that half works. That is where prompting in circles burns credits.
Auth is one strand of the wider guide to fixing a vibe-coded app. For the full Lovable picture, including payments and hosting, read taking a Lovable app to production. If your database is the real problem, the Lovable Supabase issues guide goes deeper, and fixing auth in an AI-built app covers the patterns that apply to any tool.
Start with the free vibe-code health check. If it shows more than a settings fix, a Rescue Sprint gets your auth, policies and the rest audited and fixed at a fixed price agreed after the check.
- Lovable docs: Users and authentication, checked 9 November 2026
- Lovable docs: Email authentication for your app, checked 9 November 2026
- Lovable docs: Connect to Supabase, checked 9 November 2026
- Lovable docs: Upgrade a project to TanStack Start, checked 9 November 2026
- Lovable docs: Security, checked 9 November 2026
- Lovable docs: Instructions, checked 9 November 2026
- Supabase docs: Redirect URLs, checked 9 November 2026
- Supabase docs: Auth error codes, checked 9 November 2026
- Supabase docs: onAuthStateChange, checked 9 November 2026
- Supabase docs: Initializing the client, checked 9 November 2026
- Supabase docs: Row Level Security, checked 9 November 2026
The vibe-code rescue checklist, as a PDF
About 40 checks across auth, data, payments, errors, mobile and secrets, on two pages.
Questions founders ask
Why does Lovable login work in the preview but not on my published app?
Usually because the published lovable.app address or your custom domain is not in the project's Redirect URLs. Lovable updates these automatically on its built-in backend unless you set the Site URL yourself. On your own Supabase project you have to add them in Supabase.
How do I turn off email confirmation in Lovable?
On the built-in backend, open More, then Users, then Settings, then Email, and switch on Auto-confirm email. Users can then sign in without confirming. Switch it back off before launch if you need verified addresses.
Can I make Lovable sessions last longer or time out sooner?
Not from Lovable's settings. Its docs say there are no settings for session length or inactivity timeouts. If you need a check before sensitive actions, ask Lovable to add one in code.
Why does a logged-in user see an empty page?
Row level security is on but no policy lets that user read the rows. The query succeeds and returns nothing, so the page looks empty rather than broken.

Ant
Product designer who builds MVPs, based in Nottingham. 10+ years designing digital products, and the only person at BlackFig. More about me