Symptoms
redirect_uri_mismatch/ HTTP 400 from accounts.google.com after clicking “Continue with Google.”- The address bar briefly shows
http://localhost:5173/auth/callbackeven though you started on a Vercel URL. - Supabase Auth error: “Redirect URL not allowed” or a bounce back to the Site URL, which is still localhost.
- GitHub OAuth: “The redirect_uri is not associated with this application.”
Why Lovable / Bolt / v0 do this
The first signInWithOAuth that compiles uses whatever origin the preview had. That is http://localhost:5173 (Vite) or http://localhost:3000 (Next). The same string gets pasted into the Google client as the only Authorized redirect URI, and into Supabase → Authentication → URL configuration as Site URL. It is consistent. It is also wrong the moment the app has a public hostname.
The actual fix
You must change three places. Changing only the code is the usual way to stay broken.
1. The code
await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: `${window.location.origin}/auth/callback`,
},
})
Or an env var you set per environment, e.g. VITE_SITE_URL (this one is allowed to be public). Do not leave a hardcoded localhost string in src/.
2. Supabase
Authentication → URL configuration:
- Site URL:
https://yourdomain.com(not the preview, not localhost). - Redirect URLs: add
https://yourdomain.com/auth/callback,https://YOURPROJECT.vercel.app/auth/callback, and keephttp://localhost:5173/auth/callbackfor dev.
3. Google Cloud (or GitHub)
APIs & Services → Credentials → your OAuth 2.0 Client → Authorized redirect URIs. Add the same production and preview callbacks. For Supabase-hosted OAuth the URI is often https://YOURPROJECT.supabase.co/auth/v1/callback — copy the value Supabase shows under Auth → Providers → Google, do not invent it.
Authorized JavaScript origins get the origins without the path: https://yourdomain.com and the Vercel URL.
How to know you are done
- Incognito, production URL, Google login, land on
/auth/callbackon the same host, session cookie present. - Grep the production bundle for
localhost:5173— it should not appear next toredirect. - Preview deploys still work because you added the
*.vercel.appcallback, not because Site URL is still localhost.