## TL;DR

Treat the code as single-use and short-lived: exchange it immediately, exactly once, with the same redirect_uri and client credentials used at authorize time. Most invalid_code 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 redirect
```

## Steps

1. 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.

2. Make them identical. Keycloak requires an exact match. Expected: both calls send the same string.

3. 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.

4. 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.

5. Clear any proxy or middleware that might replay the callback request. Expected: the callback URL is hit exactly once per login.

6. 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 invalid_code, which looks like a code problem but is really a retry problem. The other classic cause is a redirect_uri 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
