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