OAuth callback URL not working in prod
appears when:user clicks 'Sign in with Google' in production — Google's error page shows, or the flow redirects to localhost.
OAuth callback URL not working in prod
Everything works locally. In production, the OAuth round-trip fails: either the provider rejects the redirect URI outright, or the flow loops back to localhost because Supabase's Site URL is still pointed there.
OAuth callback URL not working in production almost always means the production redirect URI is not whitelisted in the provider console. Google throws Error 400: redirect_uri_mismatch; GitHub throws redirect_uri MUST match the registered callback URL. Copy the exact URL from the error screen, paste it into Google Cloud → Credentials, set Supabase Site URL to your production domain, and add NEXTAUTH_URL to Vercel. Ten-minute fix.
Quick fix for OAuth callback URL not working in prod
01// 1. Google Cloud Console → Credentials → your OAuth Client02// Authorized redirect URIs03https://<project-ref>.supabase.co/auth/v1/callback04https://yourapp.com/api/auth/callback/google05https://yourapp.com/auth/callback06 07// 2. Supabase Dashboard → Authentication → URL Configuration08Site URL: https://yourapp.com09Redirect URLs: https://yourapp.com/**10 http://localhost:3000/**11 12// 3. Vercel → Settings → Environment Variables (Production)13NEXTAUTH_URL=https://yourapp.com14 15// 4. Client code — dynamic redirectTo, never hard-coded16await supabase.auth.signInWithOAuth({17 provider: 'google',18 options: { redirectTo: `${window.location.origin}/auth/callback` },19});Deeper fixes when the quick fix fails
01 · Update every OAuth provider independently
Google, GitHub, and Apple maintain separate allowlists. A fix in Google Cloud does not affect GitHub. Update each provider console with the same set of production, staging, and localhost URLs.
01Google — Cloud Console → APIs & Services → Credentials → OAuth 2.0 Client IDs02GitHub — Settings → Developer settings → OAuth Apps → your app → Authorization callback URL03Apple — developer.apple.com → Certificates, IDs & Profiles → Services IDs → Return URLs02 · Strip trailing slashes and normalize www vs apex
Providers do byte-equal string matching. https://yourapp.com and https://www.yourapp.com are different origins. Pick a canonical host, redirect the other, and add only the canonical version to each provider.
03 · Fix NEXTAUTH_URL on Vercel (Auth.js specific)
Auth.js builds its callback URL from NEXTAUTH_URL. Without it, Auth.js infers the URL from incoming request headers, which on Vercel includes the internal edge runtime hostname, not your public domain. The symptom looks like a provider mismatch but the cause is an environment variable.
04 · Search the repo for hard-coded localhost URLs
Generators hard-code redirectTo: 'http://localhost:3000' in the first OAuth scaffold. Every other fix holds until this string ships to production — then the flow breaks silently because the redirect_uri sent to the provider is literally localhost.
01# Run pre-deploy — block any commit that hard-codes localhost OAuth redirects02grep -rn "redirectTo:.*localhost" src/ && {03 echo "hard-coded OAuth redirect found — use window.location.origin"04 exit 105}Why AI-built apps hit OAuth callback URL not working in prod
Lovable, Bolt, and v0 scaffold OAuth by calling supabase.auth.signInWithOAuth with a redirectTo pointed at the preview URL. That preview URL is allowlisted in the auto-provisioned Supabase project and sometimes even added to the generator's shared Google OAuth client. Everything works in preview. The moment the app is deployed to a real domain, none of those entries match — the production URL is not in Supabase's allowlist, not in Google's allowlist, and not in the hard-coded redirectTo the generator emitted.
The failure is loud in the browser (the user lands on Google's error page) but silent in logs. Your app never runs because the redirect never returns — Google halts the flow with a 400 before calling back. There is no Vercel function invocation to grep, no Supabase log entry to inspect. Founders often spend an hour searching for a bug in their callback route before realizing the callback route was never reached.
The third layer of pain is NEXTAUTH_URL. Auth.js needs this env var to build its own callback URL; without it, Auth.js infers the URL from the incoming request headers, which on Vercel includes the internal edge runtime hostname, not your public domain. The symptom looks identical to a redirect URI mismatch but the cause is an environment variable — which is why the same fix patterns appear repeatedly: touch every allowlist, touch every environment variable, and make every client-side redirect dynamic.
OAuth callback URL not working in prod by AI builder
How often each AI builder ships this error and the pattern that produces it.
| Builder | Frequency | Pattern |
|---|---|---|
| Lovable | Very high | Hard-codes redirectTo to Lovable preview URL; production apex never registered. |
| Bolt.new | High | Uses bolt.new sandbox redirect URI; custom-domain URL never propagated. |
| v0 | High | Ships Auth.js without NEXTAUTH_URL; callback URL built from Vercel edge hostname. |
| Cursor | Medium | Writes dynamic redirectTo but forgets to update Supabase Site URL from localhost. |
| Replit | Medium | Leftover replit.dev preview URL in provider allowlist shadows production host. |
| Claude Code | Low | Correct runtime code but missing documentation on which providers to update per deploy. |
| Windsurf | Low | Updates Google but not Supabase — flow bounces back to localhost after provider approves. |
| Base44 | Medium | Custom-domain added in Base44 UI but never synced to Google Cloud or Supabase. |
Related errors we fix
Stop OAuth callback URL not working in prod recurring in AI-built apps
- →Derive redirectTo from window.location.origin (browser) or NEXTAUTH_URL (server).
- →Keep one canonical host (apex or www) and redirect the other at the edge.
- →Add CI greps that block any commit containing http://localhost in auth code.
- →Maintain a single source-of-truth list of provider allowlists per environment in the repo.
- →Run a post-deploy scripted incognito sign-in that fails the pipeline on a 400 response.
Still stuck with OAuth callback URL not working in prod?
Get OAuth flowing across every environment — we touch all four layers.
- →Provider allowlists, Supabase Site URL, NEXTAUTH_URL, and client code aligned in one pass
- →Verified in an incognito smoke test before handover
- →Shipped with a documented per-environment URI list for your team
OAuth callback URL not working in prod questions
Why does my OAuth callback work on localhost but fail in production?+
What does the error redirect_uri_mismatch actually mean?+
Do I have to update Supabase too, or just the OAuth provider?+
How do I handle OAuth callback URLs for multiple environments?+
How long does fixing an OAuth callback URL take?+
Ship the fix. Keep the fix.
Emergency Triage restores service in 48 hours. Break the Fix Loop rebuilds CI so this error cannot ship again.
Hyder Shah leads Afterbuild Labs, shipping production rescues for apps built in Lovable, Bolt.new, Cursor, Replit, v0, and Base44. our rescue methodology.
OAuth callback URL not working in prod experts
If this problem keeps coming back, you probably need ongoing expertise in the underlying stack.