# OAuth2 authorization code reuse detected: same authorization code used more than once

- **ID:** `security/oauth2-authorization-code-reuse-detection`
- **Domain:** security
- **Category:** auth_error
- **Error Code:** `invalid_grant`
- **Verification:** ai_generated
- **Fix Rate:** 90%

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

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| Spring Security OAuth2 2.5.0 | active | — | — |
| Keycloak 21.0.0 | active | — | — |
| Okta 2024.02.0 | active | — | — |

## Workarounds

1. **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.** (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.
   ```
2. **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>).** (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>).
   ```
3. **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.** (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.
   ```

## Dead Ends

- **** — Longer expiration times actually increase the window for replay attacks, making the problem worse. (80% fail)
- **** — Authorization codes are randomly generated and not meant to be guessed; the issue is replay, not brute force. (50% fail)
- **** — Manual review is not scalable and cannot prevent real-time attacks; automated detection must be implemented. (70% fail)
