# oauth-callback-url-mismatches

> 

Every OAuth provider compares the `redirect_uri` your app sends with the list
registered for your client, character by character. When they differ the
provider shows its own error page and your code never runs, so there is
nothing in your logs. This is the most common reason "Continue with Google"
works locally and fails in production.

## What Better Auth sends

Better Auth builds the redirect URI from `baseURL` (the `BETTER_AUTH_URL`
environment variable):

```
<BETTER_AUTH_URL>/api/auth/callback/<provider id>
```

`http://localhost:3000/api/auth/callback/google` locally,
`https://example.com/api/auth/callback/google` in production. Open the
provider's error page and read the `redirect_uri` in its URL: that is exactly
what was sent. Compare it with the registered list.

## The one-character differences

| Sent | Registered | Why |
|---|---|---|
| `http://…` | `https://…` | `BETTER_AUTH_URL` set to http in production, or a proxy terminating TLS |
| `https://www.example.com/…` | `https://example.com/…` | the site answers on both hosts, the env names one |
| `…/callback/google/` | `…/callback/google` | trailing slash in `BETTER_AUTH_URL` (strip it) |
| `http://127.0.0.1:3000/…` | `http://localhost:3000/…` | different hosts to the provider, and to your cookies |
| `https://my-app-git-branch.vercel.app/…` | production URL only | preview deployments have their own origin |

## Provider by provider

**Google** (`Error 400: redirect_uri_mismatch`). Google Cloud console, Google
Auth Platform, Clients, your Web client, "Authorized redirect URIs". Add one
line per origin. Changes can take a few minutes to apply. While the app's
publishing status is "Testing", only listed test users can sign in, which
fails with a different error ("access blocked") that is easy to confuse with
this one.

**GitHub** ("The redirect_uri is not associated with this application"). An
OAuth app has exactly **one** "Authorization callback URL". GitHub accepts a
redirect URI that extends it with more path segments, but not a different
host or port. Create one OAuth app per environment (local, production) with
its own client id and secret.

**Microsoft Entra** (`AADSTS50011: The redirect URI ... does not match`).
App registrations, your app, Authentication. The URI must be under the **Web**
platform, not "Single-page application" (which fails later with a CORS or
token error). Also check "Supported account types" against the tenant you
send: `common` needs "any organizational directory and personal Microsoft
accounts", or personal accounts fail with `AADSTS50020`.

## Preview deployments

Preview URLs change per branch, and most providers do not accept wildcards. Pick
one:

- **No OAuth on previews.** Leave the provider keys unset in the preview
  environment. With buttons switched on by the keys, previews show email
  sign-in only. Simplest, and usually enough.
- **A stable preview domain.** Give previews a fixed alias
  (`preview.example.com`), register its callback, and set `BETTER_AUTH_URL` to
  it there.
- **An OAuth proxy.** Better Auth's `oAuthProxy` plugin routes previews through
  the production callback. More moving parts; reach for it only if testing
  OAuth on every branch matters.

## Also check

- `BETTER_AUTH_URL` matches the browser's origin exactly. Better Auth also
  uses it for the trusted-origin check, so a mismatch breaks sign-in even
  before OAuth.
- Behind a reverse proxy, the public origin is what counts, not the internal
  one the app sees.
- After changing `BETTER_AUTH_URL` or the keys, restart the server: the auth
  config is read once at startup.

## Checking your work

- Click each provider button on each environment and read the `redirect_uri`
  on the provider's page (or in the network tab) before consenting.
- Complete one sign-in per provider per environment after every domain change.

---

Agentic Boilerplate: A Next.js repo your agent already knows. Free during launch, then $99 once.

- Site map for agents: https://agenticboilerplate.com/llms.txt
- Public API: https://agenticboilerplate.com/openapi.json
- Contact: agenticstudio@gmail.com
