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

- **ID:** `security/oauth2-token-reuse-detection`
- **Domain:** security
- **Category:** auth_error
- **Error Code:** `OAuth2-409`
- **Verification:** ai_generated
- **Fix Rate:** 93%

## Root Cause

An OAuth2 authorization code was used to request a token more than once, indicating a potential replay attack where the code was intercepted and reused.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| OAuth2 2.0 | active | — | — |
| Spring Authorization Server 1.1 | active | — | — |
| Keycloak 22.0 | active | — | — |
| Okta 2023.08 | active | — | — |

## Workarounds

1. **Implement strict one-time use for authorization codes: after a code is redeemed, mark it as used in the database and reject any subsequent requests with the same code. Example: `UPDATE codes SET used=true WHERE code=? AND used=false`** (95% success)
   ```
   Implement strict one-time use for authorization codes: after a code is redeemed, mark it as used in the database and reject any subsequent requests with the same code. Example: `UPDATE codes SET used=true WHERE code=? AND used=false`
   ```
2. **Use Proof Key for Code Exchange (PKCE) to bind the authorization code to a client-generated verifier, preventing reuse even if the code is intercepted. For mobile apps, always use S256 challenge method.** (90% success)
   ```
   Use Proof Key for Code Exchange (PKCE) to bind the authorization code to a client-generated verifier, preventing reuse even if the code is intercepted. For mobile apps, always use S256 challenge method.
   ```

## Dead Ends

- **** — Increasing the authorization code expiration time to reduce user friction makes the window for reuse attacks larger, worsening the security issue. (60% fail)
- **** — Simply ignoring the error and allowing the second request to succeed breaks the OAuth2 spec and enables token theft. (80% fail)
- **** — Some try to use a different code for each request by generating new codes, but this doesn't address the fact that the original code was compromised. (20% fail)
