invalid_grant
security
auth_error
ai_generated
true
OAuth2 authorization code reuse detected: same authorization code used more than once
ID: security/oauth2-authorization-code-reuse-detection
90%Fix Rate
88%Confidence
1Evidence
2023-11-20First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| Spring Security OAuth2 2.5.0 | active | — | — | — |
| Keycloak 21.0.0 | active | — | — | — |
| Okta 2024.02.0 | active | — | — | — |
Root Cause
The authorization server fails to properly mark authorization codes as consumed after first use, allowing an attacker to replay a previously intercepted code to obtain a new access token.
generic中文
授权服务器未能正确标记授权码在首次使用后已消耗,允许攻击者重放之前截获的授权码以获取新的访问令牌。
Official Documentation
https://datatracker.ietf.org/doc/html/rfc6749#section-10.5Workarounds
-
95% success Ensure the authorization server marks the code as consumed atomically upon first use. For example, in a database-backed implementation, use a transaction: UPDATE auth_codes SET consumed=true WHERE code=? AND consumed=false. If affected rows is 0, reject the request.
Ensure the authorization server marks the code as consumed atomically upon first use. For example, in a database-backed implementation, use a transaction: UPDATE auth_codes SET consumed=true WHERE code=? AND consumed=false. If affected rows is 0, reject the request.
-
90% success Implement a one-time use token pattern: after issuing the access token, immediately invalidate the authorization code from the store (e.g., Redis: DEL auth_code:<code>).
Implement a one-time use token pattern: after issuing the access token, immediately invalidate the authorization code from the store (e.g., Redis: DEL auth_code:<code>).
-
85% success Add a nonce or state parameter that must be unique per authorization request and validated during token exchange, preventing replay even if the code is intercepted.
Add a nonce or state parameter that must be unique per authorization request and validated during token exchange, preventing replay even if the code is intercepted.
中文步骤
Ensure the authorization server marks the code as consumed atomically upon first use. For example, in a database-backed implementation, use a transaction: UPDATE auth_codes SET consumed=true WHERE code=? AND consumed=false. If affected rows is 0, reject the request.
Implement a one-time use token pattern: after issuing the access token, immediately invalidate the authorization code from the store (e.g., Redis: DEL auth_code:<code>).
Add a nonce or state parameter that must be unique per authorization request and validated during token exchange, preventing replay even if the code is intercepted.
Dead Ends
Common approaches that don't work:
-
80% fail
Longer expiration times actually increase the window for replay attacks, making the problem worse.
-
50% fail
Authorization codes are randomly generated and not meant to be guessed; the issue is replay, not brute force.
-
70% fail
Manual review is not scalable and cannot prevent real-time attacks; automated detection must be implemented.