# Google OAuth Redirect Doctor — redirect_uri_mismatch > Free, client-side checker that finds why Google throws "Error 400: redirect_uri_mismatch" (or `invalid_request`) during OAuth sign-in, and gives the exact fix for your code and for Google Cloud Console's Authorized redirect URIs. Paste the `redirect_uri` from Google's error page, your Authorized redirect URIs / JavaScript origins from Google Cloud Console, and which stack you're using (NextAuth/Auth.js, Supabase, Firebase, Passport, Django allauth, Laravel Socialite, `google-auth-oauthlib`, Expo AuthSession, Flutter, Postman, or gcloud), and it computes the exact `redirect_uri` your stack should send, diffs it byte-for-byte against what Google saw and against your console entries, and reports precisely which component differs — no account, no backend, nothing you type leaves your browser. ## What it checks - Invisible/whitespace characters in the pasted `redirect_uri` that look identical to the correct value but fail Google's exact-match check. - `http` used anywhere except localhost — Google requires HTTPS everywhere else. - A raw IP address as the host, a query string, or a fragment — Google's redirect_uri validation rejects all three. - A custom scheme sent to a "Web application" OAuth client instead of Android/iOS/Desktop. - Byte-for-byte diff of scheme, host (`www` vs. apex, `localhost` vs. `127.0.0.1`), port, path (trailing slash, letter case) between what your stack computes and what Google saw. - Whether the right value is actually present in Authorized redirect URIs — Google's allow-list has no wildcards, unlike Supabase's — with the closest existing entry shown if not. - Authorized JavaScript origins for Google Identity Services (One Tap / popup sign-in). - Stack-specific expected callbacks: NextAuth/Auth.js (`/api/auth/callback/google`), Supabase (`https://.supabase.co/auth/v1/callback`, not your app's URL), Firebase (`https:///__/auth/handler`), Passport, django-allauth (`/accounts/google/login/callback/`), Laravel Socialite, `google-auth-oauthlib`'s local-server loopback flow, Expo AuthSession (proxy vs. native), Flutter `google_sign_in` (no redirect_uri at all), Postman, and `gcloud auth application-default login`'s fixed port 8085. - Preview-deployment traps — no wildcards means each `*.vercel.app` preview needs its own exact entry or a stable callback domain. - The "Testing" consent-screen red herring — `access_denied` from an untested account is a different error than `redirect_uri_mismatch`. ## Who it's for Any developer hitting Google's "Error 400: redirect_uri_mismatch" or "invalid_request" during sign-in — via Next.js/NextAuth/Auth.js, Supabase, Firebase, Passport, Django allauth, Laravel Socialite, `google-auth-oauthlib`, Expo AuthSession, Flutter, Postman, or `gcloud`. ## How it works Static HTML plus one dependency-free JavaScript file, `doctor-google.js`. All checks run in your browser against the values you type; the tool has no backend and makes no request that carries your configuration anywhere. ## Privacy No account, no login, no cookies for the tool itself, no server-side processing of your config. The only analytics are anonymous usage counts (event name + count, never the content of what you entered) sent to a self-hosted Umami instance. ## Links - Tool: https://arling.sk/google-oauth-redirect-doctor/ - Full reference (worked example + FAQ): https://arling.sk/google-oauth-redirect-doctor/llms-full.txt - Source code: https://github.com/AndryRoby/google-oauth-redirect-doctor - Sibling tool for Supabase Auth on the web (Next.js/Vite/SvelteKit): https://arling.sk/supabase-redirect-doctor/ - Sibling tool for Supabase Auth on Flutter: https://arling.sk/flutter-supabase-doctor/ - Sibling tool for Supabase Auth on Expo / React Native: https://arling.sk/expo-supabase-auth-doctor/ - Hub (more ARLing tools): https://arling.sk/ ## Contact Built by ARLing s. r. o. (Bratislava, Slovakia). andrej@arling.sk