Auth

Google sign-in fails on Replit with redirect_uri_mismatch: fix it

Short answer

  • Google compares the redirect URI your app sends, character by character, with the list in Google Cloud Console.
  • Add the exact production callback for your .replit.app domain and your custom domain, with https.
  • Build the callback from one APP_URL setting, not from the request host or the first entry of REPLIT_DOMAINS.

Sign in with Google works in the preview. On the live app, users get Error 400: redirect_uri_mismatch. Google is strict: the redirect URI your app sends must exactly match one of the URIs you registered. The fix is to make your app send a predictable URL, and register it.

Symptoms

  • Error 400: redirect_uri_mismatch after clicking Sign in with Google.
  • The error details show a replit.dev, http:// or unexpected domain in redirect_uri.
  • Login works on .replit.app but not on the custom domain, or the reverse.
  • After login, users land on the preview URL instead of production.

Likely causes

  1. Only the development callback is registered in Google Cloud Console.
  2. The app builds the callback with http:// because it sits behind Replit's HTTPS proxy.
  3. The callback is built from the first domain in REPLIT_DOMAINS or from the request host, which can change.
  4. A trailing slash or path difference (/auth/google/callback vs /api/auth/google/callback).
  5. The OAuth consent screen is still in testing mode, so only test users can sign in.

Step-by-step fix

1. Read the URI Google received

On the error page, open the error details. Copy the redirect_uri value. That is exactly what your app sent.

2. Set one APP_URL

Add a deployment secret APP_URL=https://yourdomain.com and build every absolute URL from it, including the OAuth callback.

const callbackURL = `${process.env.APP_URL}/api/auth/google/callback`;
passport.use(new GoogleStrategy({ clientID, clientSecret, callbackURL }, verify));

In Express, also set app.set("trust proxy", 1) so the app knows the original request was HTTPS.

3. Register every real callback

In Google Cloud Console, open your OAuth client and add each callback you use under Authorized redirect URIs: the custom domain, the .replit.app domain if users can reach it, and your dev URL if you test in the preview. Add the matching origins under Authorized JavaScript origins. Save and wait a few minutes.

4. Publish the consent screen

If only some accounts can sign in, the OAuth app may still be in testing mode. Move it to production in the consent screen settings. Google may require domain verification for some scopes.

5. Consider Replit Auth

If you only need sign-in and not Google API access, Replit Auth handles development, .replit.app and custom domains for you. With Replit-managed Clerk auth, use the exact values shown in the Auth pane.

Copy-paste prompt for Replit Agent

Open a new Agent chat (a fresh chat keeps old attempts out of its context) and paste this:

Google sign-in on my published Replit app fails with redirect_uri_mismatch. The redirect_uri in Google's error is: [paste].
Please:
1. Build the OAuth callback URL from an APP_URL environment variable instead of the request host or REPLIT_DOMAINS.
2. Set app.set("trust proxy", 1) so redirects and cookies use https behind Replit's proxy.
3. After login, redirect to a path relative to APP_URL, never to the dev domain.
4. Print the exact list of Authorized redirect URIs and JavaScript origins I must add in Google Cloud Console for production and development.
Do not change the user model or session logic.

How to verify the fix

  • Sign in with Google on the live custom domain in a private window, with an account that is not a test user.
  • After login you land on the production domain, and the session persists after a refresh.
  • The .replit.app URL either works too or redirects to the custom domain.

If login succeeds but users are logged out right away, read why login breaks after deploy.

FAQ

What causes redirect_uri_mismatch on Replit?

The callback URL your app sends to Google is not exactly one of the Authorized redirect URIs in Google Cloud Console. On Replit this is usually the dev URL, http instead of https, or a different domain than the one you registered.

Can I add replit.dev URLs to Google OAuth?

You can add a specific dev callback URL as a redirect URI for testing. Dev URLs can change, so production should use your published domain.

Do I need trust proxy for OAuth on Replit?

In Express, yes. The app sits behind Replit's HTTPS proxy, and trust proxy lets it see the original https protocol for redirects and secure cookies.

Get a free audit