What is Token Rotation?
Token rotation is a security mechanism where refresh tokens are single-use only. Each time a refresh token is used to obtain a new access token, the old refresh token is invalidated and a new one is issued. This prevents stolen refresh tokens from being useful to attackers for extended periods.Why Token Rotation Matters
Without Rotation
Problem: A stolen refresh token can be used repeatedly for 7 days
- Attacker steals token from compromised device
- Attacker uses token to get access tokens whenever needed
- Legitimate user continues using same token
- No one notices the breach
With Rotation
Solution: Stolen tokens become useless quickly
- Attacker steals token from compromised device
- Legitimate user refreshes → old token invalidated
- Attacker tries to use old token → DETECTED
- System revokes all tokens for that user
- Breach is detected and contained
How It Works
Normal Token Refresh Flow
Server validates token
The server looks up the token in the database (AuthService.cs:116-118):Then checks if it’s active (AuthService.cs:134-135):
Server rotates the token
The old token is marked as revoked and replaced (AuthService.cs:137-144):The database now contains:
| Token | Status | ReplacedBy | Reason |
|---|---|---|---|
| ABC123 | Revoked | XYZ789 | Rotación normal |
| XYZ789 | Active | null | - |
Detecting Token Reuse Attacks
The magic happens when someone tries to use an already-rotated token.System revokes token family
The This follows the chain:
RevokeDescendantTokensAsync method recursively invalidates all descendant tokens (AuthService.cs:235-251):ABC123 → XYZ789 → DEF456 → …All tokens in the family are revoked:| Token | Status | ReplacedBy | Reason |
|---|---|---|---|
| ABC123 | Revoked | XYZ789 | Rotación normal |
| XYZ789 | Revoked | DEF456 | Token reuse detectado |
| DEF456 | Revoked | null | Token reuse detectado |
Token Family Visualization
Here’s how a token family evolves over time:Token Storage Schema
TheRefreshToken entity tracks the complete rotation chain (RefreshToken.cs:1-26):
Automatic Token Cleanup
To prevent the database from growing indefinitely, old tokens are automatically removed (AuthService.cs:224-233):- All active tokens
- Inactive tokens from the last 30 days (for forensics)
Edge Cases and Scenarios
What if the user has multiple devices?
What if the user has multiple devices?
Each device gets its own refresh token during login. Token rotation is per-device:
- Device A: Token family
A1 → A2 → A3 - Device B: Token family
B1 → B2 → B3 - Device C: Token family
C1 → C2
A family is revoked. Devices B and C continue working.All tokens are stored in User.RefreshTokens collection (User.cs:18).What if the network is flaky?
What if the network is flaky?
Problem: Client sends refresh request, server responds with new token, but response is lost. Client retries with old token.Result: Detected as reuse attack, all tokens revoked.Mitigation:
- Use idempotency keys for refresh requests
- Implement exponential backoff with jitter
- Consider a short grace period (e.g., 5 seconds) where old token is still valid
Can an attacker refresh first?
Can an attacker refresh first?
Scenario: Attacker steals token and uses it before the legitimate user.What happens:
- Attacker refreshes with stolen token → gets new token
- Legitimate user tries to refresh with old token → reuse detected
- All tokens revoked, including attacker’s new token
- Both attacker and user are logged out
What about token expiration?
What about token expiration?
Expired tokens cannot trigger reuse detection because they’re rejected before the reuse check (AuthService.cs:134-135):This prevents false positives when users try to use legitimately expired tokens.
Comparison with Other Strategies
No Rotation
Security: ⭐⭐UX: ⭐⭐⭐⭐⭐Stolen tokens work until expiry (7 days). No breach detection.
Token Rotation
Security: ⭐⭐⭐⭐⭐UX: ⭐⭐⭐⭐Stolen tokens detected on next use. False positives from network issues.
Rotation + Grace Period
Security: ⭐⭐⭐⭐UX: ⭐⭐⭐⭐⭐Small window (5s) where old token still works. Reduces false positives.
Monitoring and Forensics
Token rotation generates valuable security logs:- Frequency of reuse detections per user
- IP addresses involved in reuse events
- Time delta between token creation and reuse
- Geographic location of IPs (if available)
CreatedByIp: Where token was originally issued (AuthService.cs:220)RevokedByIp: Where revocation was requested (AuthService.cs:140, 164)RevocationReason: Why token was revoked (AuthService.cs:142, 165, 247)CreatedAt: Timestamp for age analysis (RefreshToken.cs:9)
- Compromised devices
- Phishing attacks
- Credential stuffing attempts
- Unusual access patterns
Security Considerations
Why not make refresh tokens JWTs? Refresh tokens are stored in the database anyway (for rotation tracking), so there’s no benefit to making them JWTs. Random bytes are simpler and more efficient (TokenService.cs:58-66).
Best Practices
- Keep access tokens short-lived (15 minutes or less)
- Implement token rotation (as shown here)
- Log all reuse detections for security monitoring
- Store IP addresses for forensic analysis
- Clean up old tokens to prevent database bloat
- Consider device fingerprinting for additional validation
- Use secure channels (HTTPS only) for token transmission
- Never log token values (only metadata)
Related Topics
Authentication Flow
See how token rotation fits into the complete auth flow
Security Features
Explore other security mechanisms in the service
API Reference
Complete endpoint documentation