Error 400: redirect_uri_mismatch

Google stopped the sign-in because the return address your app sent isn’t on the OAuth client’s list of approved redirect URIs.

Google sign-in page
Access blocked: This app's request is invalid You can't sign in because this app sent an invalid request. You can try again later, or contact the developer about this issue. Error 400: redirect_uri_mismatch

Also appears as

  • You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy. If you're the app developer, register the redirect URI in the Google Cloud Console. Request details: redirect_uri=https://abcdefghijklmnopqrst.supabase.co/auth/v1/callback

Prompt to fix it

Google sign-in fails with "Error 400: redirect_uri_mismatch". Find how the app starts Google sign-in and work out the exact redirect URI it sends to Google, including scheme, host, port, path, and trailing slash. If we use Supabase Auth, that URI is the Supabase callback (https://<project-ref>.supabase.co/auth/v1/callback), and the app’s own URLs belong in Supabase’s Redirect URLs. Tell me exactly which URIs to add in Google Cloud Console and in Supabase for local development and production. Don’t change the client ID or secret.

Paste into Layerwise or any AI coding tool.

What it means

After someone picks a Google account, Google sends them back to a redirect URI: the address that receives the sign-in result. Google only sends people to addresses listed in your OAuth client, and the match must be exact, down to http or https, www, the port, the path, and any trailing slash.

With Supabase Auth, Google sends people back to Supabase first, so the URI Google needs is your project’s callback, https://<project-ref>.supabase.co/auth/v1/callback. Your app’s own addresses, like http://localhost:5173, go in Supabase’s Redirect URLs list. Mixing up those two lists is the most common cause.

You don’t have to guess the value. Click “error details” on Google’s page: the redirect_uri= line shows exactly what was sent. Add that to the OAuth client, then allow a few minutes for the change to take effect.

Common causes

  • The Google client lists the app’s own URL, but Supabase sends Google its /auth/v1/callback URL.
  • The app moved to a new domain or preview URL, and the auth library builds the callback from the current address, such as Auth.js’s /api/auth/callback/google.
  • A small difference: http versus https, www versus no www, a different port, or a trailing slash.
  • The client ID in the app or in Supabase belongs to a different OAuth client or Google Cloud project than the one you edited.

How to fix it

  1. On the Google error page, click “error details” and copy the redirect_uri value.
  2. In Google Cloud Console, open Google Auth Platform, then Clients, and select the web client whose ID matches the one in your app or Supabase.
  3. Add the exact value under Authorized redirect URIs and save. For Supabase, that’s the callback URL shown on the Google provider page in Supabase.
  4. In Supabase, add your app’s addresses, both localhost and the published domain, under Authentication, then URL Configuration, then Redirect URLs.
  5. Wait a few minutes, then try again in a private window.
All errors
AuthSessionMissingError: Auth session missing!

AuthSessionMissingError: Auth session missing

A Supabase auth call needed a signed-in user, but the client making it had no session, often because it runs on the server without cookies.

AuthApiError: Invalid login credentials

Invalid login credentials

Supabase couldn’t match that email and password to an account that signs in with a password, and it deliberately doesn’t say which part was wrong.

This page isn’t working my-app.com redirected you too many times. Try deleting your cookies. ERR_TOO_MANY_REDIRECTS

ERR_TOO_MANY_REDIRECTS

The site keeps redirecting the browser in a circle, usually between HTTP and HTTPS or between two domains, so the browser stops trying.

JWT expired

JWT expired

A request carried a sign-in token past its expiry time, usually because code saved the token once instead of using the refreshed one.

Build with an agent that checks its work

The Layerwise agent clicks through the live preview and reads the console, so it catches errors before you do.