1 min lesson
Refresh-token rotation with reuse detection
Use the lesson to explain "How does refresh-token rotation with reuse detection actually catch a stolen token and what should the system do when it fires?" Then make the next move clear.
Step 1 of 2
Refresh-token rotation with reuse detectioncatching theft
Every time a refresh token is redeemed, issue a new one and invalidate the old. If the old one is ever presented again, you have a problem: either the legitimate client or a thief is replaying it and you can't tell which - so you revoke the whole token family and force re-login.
- Normal redeem
- Old token consumed, new token issued, family chain advances
- Old token reused
- Reuse detected - revoke the entire family, force re-auth
- Result
- A stolen refresh token is good for at most one use before it trips the alarm
Reuse detection turns a silent theft into a loud, self-healing event.
Learn more
Full explanation
Revocation: pick your latency
Revocation: pick your latencyimmediacy vs hot-path cost
- Strategy
- Short TTL + token-version check at refresh
- Revocation speed
- Within one access-token TTL
- Hot-path cost
- None on normal requests
- Strategy
- Deny-list of revoked token ids
- Revocation speed
- Immediate
- Hot-path cost
- A lookup (cacheable) per request
- Strategy
- Pure long-lived JWT, no list
- Revocation speed
- Only at expiry
- Hot-path cost
- None - but effectively can't revoke
- Strategy
- Server-side sessions
- Revocation speed
- Immediate
- Hot-path cost
- A store lookup per request
| Strategy | Revocation speed | Hot-path cost |
|---|---|---|
| Short TTL + token-version check at refresh | Within one access-token TTL | None on normal requests |
| Deny-list of revoked token ids | Immediate | A lookup (cacheable) per request |
| Pure long-lived JWT, no list | Only at expiry | None - but effectively can't revoke |
| Server-side sessions | Immediate | A store lookup per request |
There's no zero-cost instant revocation; choose the trade per surface.
For most of Cursor's traffic, short TTLs plus a token_version check are enough. Reserve an immediate deny-list for the high-stakes cases - a confirmed compromised account, an emergency "log this person out now" - where a few minutes of staleness is unacceptable.