OAuth2 token endpoint returned HTTP 400: invalid_grant with error_description 'Invalid authorization code'
ID: security/oauth2-token-endpoint-http-400
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| Spring Security 6.0.0 | active | — | — | — |
| Passport.js 0.6.0 | active | — | — | — |
| Okta SDK 1.0.0 | active | — | — | — |
| Express OAuth2 Server 3.0.0 | active | — | — | — |
Root Cause
The authorization code used in the token exchange is invalid, expired, or has already been used, often due to a race condition where multiple requests attempt to use the same code or the code was issued for a different client ID.
generic中文
令牌交换中使用的授权码无效、已过期或已被使用,通常是由于多个请求尝试使用同一个授权码的竞态条件,或者该授权码是为不同的客户端ID签发的。
Official Documentation
https://datatracker.ietf.org/doc/html/rfc6749#section-5.2Workarounds
-
90% success Ensure the authorization code is used exactly once. If the token exchange fails due to a network error, do not automatically retry with the same code; instead, redirect the user to re-authenticate.
Ensure the authorization code is used exactly once. If the token exchange fails due to a network error, do not automatically retry with the same code; instead, redirect the user to re-authenticate.
-
80% success Check that the client ID and redirect URI used in the token request exactly match those used in the authorization request. Mismatches cause the code to be rejected.
Check that the client ID and redirect URI used in the token request exactly match those used in the authorization request. Mismatches cause the code to be rejected.
-
75% success If the code is being consumed by a background job or multiple workers, add a lock or a state machine to ensure only one request can exchange the code at a time.
If the code is being consumed by a background job or multiple workers, add a lock or a state machine to ensure only one request can exchange the code at a time.
中文步骤
确保授权码只使用一次。如果令牌交换因网络错误失败,不要自动使用相同的授权码重试;而是将用户重定向到重新认证。
检查令牌请求中使用的客户端ID和重定向URI是否与授权请求中使用的完全匹配。不匹配会导致授权码被拒绝。
如果授权码被后台任务或多个工作进程消费,添加锁或状态机以确保同一时间只有一个请求可以交换该授权码。
Dead Ends
Common approaches that don't work:
-
100% fail
Retrying the token exchange immediately with the same authorization code will always fail because the code is single-use and has been consumed on the first attempt.
-
40% fail
Increasing the authorization code expiration time on the server can help with delays but does not fix the root cause if the code is being reused or mismatched.
-
50% fail
Clearing browser cookies and restarting the flow may work but is not a systematic fix; it only masks the issue for the user and doesn't address the underlying client-side bug.