keycloak invalid_code error on token exchange after redirect
Fixes Keycloak token exchanges that fail with invalid_code right after the redirect. Use when the authorization code is rejected at the token endpoint. Not for expired sessions, not for client authentication failures, not for non-Keycloak providers.
TL;DR
Treat the code as single-use and short-lived: exchange it immediately, exactly once, with the same redirecturi and client credentials used at authorize time. Most invalidcode failures are a reused or expired code, or a redirect_uri that does not match character-for-character.
keycloak invalid_code error on token exchange after redirectSteps
- Log the exact redirect_uri sent on the authorization request and the one sent on the token exchange. Compare them character for character, including trailing slashes and query strings. Expected: you found whether they differ.
- Make them identical. Keycloak requires an exact match. Expected: both calls send the same string.
- Check the code is exchanged once and fast. Add logging around the exchange call and confirm no retry, no double-submit, and no long gap after the redirect. Expected: one exchange attempt within seconds of the redirect.
- Verify the client authentication on the token call: the same client id, and the correct secret or private-key JWT for a confidential client. Expected: client auth succeeds independently of the code.
- Clear any proxy or middleware that might replay the callback request. Expected: the callback URL is hit exactly once per login.
- Retry the full login flow fresh. Expected: the token endpoint returns tokens.
Use this when
- Keycloak returns invalid_code at the token endpoint right after redirect.
- A generated client retries the exchange on failure, burning the single-use code.
- The redirect URI was assembled by string concatenation and may differ between calls.
Not for this skill when
- The error names the client authentication (invalid_client) - fix the secret, not the code.
- The session expired before the exchange - that is a session-timeout issue.
- The provider is not Keycloak; code semantics are similar but the knobs differ.
Variant phrasings
- Keycloak invalid_code on token exchange
- Keycloak authorization code rejected after redirect
- Keycloak code exchange fails invalid code
Why it happens
Authorization codes are single-use and expire in seconds to minutes. A retry-after-failure burns the code on the first attempt and fails the second with invalidcode, which looks like a code problem but is really a retry problem. The other classic cause is a redirecturi mismatch, which Keycloak reports as an invalid code rather than a URI error.
Edge cases
- Browser back-button or double-click can fire the callback twice; make the callback handler idempotent or redirect immediately.
- Clock skew between your server and Keycloak shortens the effective code lifetime; keep clocks in sync.
- Public clients with PKCE must send the same code_verifier; a missing or mismatched verifier also surfaces as an invalid code.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_y-3CgmCvuaRIU9jwKP0z7g