Problem
Revoking a token via POST /api/admin/tokens/{id}/revoke updates the database but does not affect the authentication middleware. Revoked tokens continue to pass authentication indefinitely.
Evidence
Tested 2026-04-24:
- Created test token (ID 79) → verified it passes auth (HTTP 406 = past auth, MCP content negotiation error)
- Revoked via admin API →
{"success":true,"message":"Token 已撤销"}
- Tested at 0s, 1s, 3s, 5s, 64s, 103s after revocation → all still pass auth (HTTP 400/406, not 401/403)
- Control: invalid token → correctly returns 403
| Time after revoke |
Revoked token |
Invalid token (control) |
| 0s |
406 (auth passed) |
403 |
| 5s |
406 (auth passed) |
403 |
| 64s |
400 (auth passed) |
403 |
| 103s |
400 (auth passed) |
403 |
Root Cause (hypothesis)
Token is JWT (HS256). Auth middleware validates signature only, never checks database revocation status. jti field exists but no revocation list is consulted.
Impact
Token leak = no kill switch. Admin cannot invalidate a compromised token. Combined with #172 (no rate limiting), attacker has unlimited, irrevocable access.
Suggested Fix
- Auth middleware must check token revocation status on every request (DB or cache lookup by
jti)
- If using cache: TTL ≤ 60s, or use pub/sub invalidation
- Consider adding token to a deny-list on revoke
Priority
P0 — parallel with #172.
Related
Problem
Revoking a token via
POST /api/admin/tokens/{id}/revokeupdates the database but does not affect the authentication middleware. Revoked tokens continue to pass authentication indefinitely.Evidence
Tested 2026-04-24:
{"success":true,"message":"Token 已撤销"}Root Cause (hypothesis)
Token is JWT (HS256). Auth middleware validates signature only, never checks database revocation status.
jtifield exists but no revocation list is consulted.Impact
Token leak = no kill switch. Admin cannot invalidate a compromised token. Combined with #172 (no rate limiting), attacker has unlimited, irrevocable access.
Suggested Fix
jti)Priority
P0 — parallel with #172.
Related