MeatButton

OAuth "redirect_uri_mismatch"

Why your social login broke after deploying

You built "Sign in with Google" (or GitHub, or Facebook, or any OAuth provider). It worked locally. You deployed. Now users click the login button and get:

Error 400: redirect_uri_mismatch
The redirect URI in the request does not match the ones
authorized for the OAuth client.

Or some variation — "invalid redirect_uri," "redirect_uri not registered," or just a generic "something went wrong" page from the provider.

What's happening

OAuth login works like this:

  1. Your app sends the user to Google (or GitHub, etc.) to sign in
  2. The user signs in on Google's page
  3. Google sends the user back to your app at a specific URL — the redirect URI
  4. Your app receives a code at that URL and exchanges it for user data

The redirect URI is the URL Google sends the user back to after login. For security, Google only sends users to URLs you've pre-registered in your OAuth app settings. If the URL your app requests doesn't exactly match one you registered, Google rejects it.

"Exactly match" means exactly. http vs https, www vs no www, trailing slash vs no trailing slash — any difference triggers the error.

Why it broke after deploying

When you were developing locally, your redirect URI was something like:

http://localhost:3000/auth/callback

That's what you registered with Google and that's what your code sends. It worked because the URLs matched.

Now your app is deployed at https://myapp.com. Your code is still sending http://localhost:3000/auth/callback as the redirect URI, or it's sending https://myapp.com/auth/callback but you haven't added that URL to Google's allowed list. Either way, it doesn't match, and Google rejects it.

How to fix it

Step 1: Find your OAuth provider's settings.

Step 2: Add your production redirect URI. It needs to be the exact URL your deployed app uses. Common format:

https://yourapp.com/auth/callback
https://yourapp.com/api/auth/callback/google
https://yourapp.vercel.app/auth/callback

The exact path depends on your auth library. Check your code for the callback route.

Step 3: Keep your local URI too. You need both — the localhost one for development and the production one for your deployed app. Most providers let you register multiple redirect URIs.

Step 4: Make sure your app sends the right URI. Check your code or environment variables. There's usually an OAUTH_REDIRECT_URI, NEXTAUTH_URL, or similar variable that needs to match your deployment URL.

# Local .env
NEXTAUTH_URL=http://localhost:3000

# Production environment variables
NEXTAUTH_URL=https://yourapp.com

Common gotchas

HTTP vs HTTPS. http://yourapp.com/callback is not the same as https://yourapp.com/callback. Production should always be HTTPS.

Trailing slashes. /callback is not the same as /callback/. Pick one and be consistent.

www vs no www. https://www.yourapp.com/callback is not the same as https://yourapp.com/callback. Use whichever your domain resolves to.

Vercel preview URLs. If you're on Vercel, every pull request gets a unique preview URL. These won't match your registered redirect URI. You either need to add each preview URL (impractical) or only test OAuth on your production domain.

Supabase auth. If you're using Supabase for auth, the redirect URI is configured in the Supabase dashboard under Authentication → URL Configuration. You need to add your production URL to the "Redirect URLs" list there, not just in the OAuth provider.

Session and JWT issues

Sometimes login appears to work but the session immediately expires or the user gets kicked back to login. This isn't a redirect URI problem — it's usually:

Why AI gets this wrong

AI generates auth code that works for one environment — usually local development. It hardcodes localhost:3000 as the redirect URI, or it uses environment variables but doesn't tell you that you need to set them differently in production. The code works perfectly on your machine and breaks the moment you deploy because OAuth configuration is an environment-specific concern that AI treats as a code concern.

Auth is one of those things that's deceptively simple to set up and genuinely hard to get right across environments. If you're fighting OAuth errors, the problem is almost never your code logic — it's the configuration mismatch between what your code expects and what the provider has registered.

Auth still broken?

MeatButton connects you with developers who've configured OAuth across hundreds of environments. They can diagnose your specific setup, fix the configuration, and make sure login works everywhere. First one's free.

Get MeatButton