flashman
← All posts

OAuth invalid_grant errors: debug the token exchange

Debug OAuth invalid_grant errors by checking authorization code reuse, redirect URI encoding, client clocks, token requests, and JSON errors locally safely.

2026-06-22 · 6 min read · Rahul Chitturi

  • oauth
  • auth
  • debugging

The OAuth authorization screen can succeed and still leave your app with invalid_grant during the token exchange. That error is intentionally vague because providers do not want to leak details about authorization codes, clients, or refresh tokens.

Treat invalid_grant as a token request debugging problem. Capture the non-secret fields, compare them with the authorization request, and verify timing before changing framework callbacks or rotating every credential.

Start with the authorization code

Authorization codes are short-lived and single-use. A retry from the browser, a double form submit, or two backend instances racing to exchange the same code can turn a valid login into invalid_grant.

  • Exchange each code once and store no reusable copy
  • Check whether the provider reports code already used or expired
  • Make callback handlers idempotent around redirects and page refreshes
  • Avoid logging full codes in tickets or shared dashboards

Match redirect_uri exactly again

Many providers require the redirect_uri in the token request to match the value from the authorization request. If one request uses a trailing slash, a different host, or a double-encoded query value, the token endpoint can reject the grant even though the browser callback reached your app.

Decode the value once, compare it with the registered callback, then encode it once when building the token request body.

Check clocks, clients, and environments

Invalid_grant can also mean the grant was issued to a different client or has already expired. Staging client IDs, production redirect URLs, preview deployment hosts, and unsynchronized server clocks all create symptoms that look like provider instability.

  • Confirm client ID, issuer, callback host, and token endpoint belong together
  • Compare server time with the provider's expected token lifetime
  • Inspect whether local development uses http while production uses https
  • Keep refresh token rotation settings consistent across environments

Read the JSON error body

Token endpoints often return useful fields such as error_description, trace IDs, or policy names. Format the JSON response before searching logs. If a JWT is returned in a partial or follow-up flow, decode only non-production tokens and validate issuer, audience, and expiration.

For repeated incidents, diff a working token request against a failing one with secrets redacted. The difference is usually a redirect URI, client ID, timestamp, or grant type.

A Flashman workflow

Flashman keeps this debugging loop in the browser, which is useful when OAuth data includes tenant names, callback hosts, or non-production tokens. Redact secrets, prefer test values, and clear the tab when the incident is resolved.

  • Use the URL encoder/decoder to inspect redirect_uri and nested return URLs
  • Format token endpoint JSON so provider hints are readable
  • Convert Unix timestamps when checking code and token expiry windows
  • Decode test JWTs locally to inspect issuer, audience, and exp claims

Try these tools