# Race condition in token revocation allows stale token reuse

- **ID:** `security/race-condition-in-token-revocation`
- **Domain:** security
- **Category:** runtime_error
- **Error Code:** `AUTH_RACE_002`
- **Verification:** ai_generated
- **Fix Rate:** 78%

## Root Cause

A race condition occurs when a token is revoked but a concurrent request validates it before the revocation is fully committed to the database, allowing stale token reuse.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| JWT 0.12.0 | active | — | — |
| OAuth2 2.0 | active | — | — |
| Redis 7.2 | active | — | — |

## Workarounds

1. **Use a distributed lock (e.g., Redis Redlock) around the revocation and validation operations to ensure atomicity. Example in Node.js:
const lock = await redisClient.acquireLock('token_revoke_lock', 5000);
try {
    await revokeTokenInDB(tokenId);
    // Validation will now see the revoked state
} finally {
    await lock.release();
}** (85% success)
   ```
   Use a distributed lock (e.g., Redis Redlock) around the revocation and validation operations to ensure atomicity. Example in Node.js:
const lock = await redisClient.acquireLock('token_revoke_lock', 5000);
try {
    await revokeTokenInDB(tokenId);
    // Validation will now see the revoked state
} finally {
    await lock.release();
}
   ```
2. **Implement a short blacklist (5-10 seconds) in memory (e.g., Guava Cache) for recently revoked tokens before checking the database, reducing the race window.** (80% success)
   ```
   Implement a short blacklist (5-10 seconds) in memory (e.g., Guava Cache) for recently revoked tokens before checking the database, reducing the race window.
   ```

## Dead Ends

- **Use a simple cache like Memcached with a short TTL to store revoked tokens** — Caching with TTL can expire before the revocation is processed, still allowing reuse; also, cache inconsistency across nodes worsens the race. (85% fail)
- **Add a small sleep() before validation after revocation** — Sleeping is non-deterministic and doesn't guarantee atomicity; it also degrades performance. (90% fail)
