← Recipes

阅读中文版本

Support Global Logout with Token Revocation

Track token families or a per-user token version, revoke on logout-everywhere and password change, and validate the version on every request.

~40 minauthenticationsecuritysession

Task

Make it possible to invalidate all of a user sessions at once when a credential may be compromised.

When to use this

A user changes their password or reports a stolen device, but existing JWTs stay valid until they naturally expire, so the attacker keeps access.

Prerequisites

  • A store for token versions or revocation lists
  • A request-time validation hook

Steps

1. Store a per-user token version or a list of active token families.

Expected output: The server can invalidate issued tokens.

2. On logout-everywhere or password change, bump the version or revoke the families.

Expected output: All outstanding tokens become invalid.

3. Validate the token version on each request.

Expected output: Revoked tokens are rejected immediately, not at expiry.

4. Keep access tokens short-lived so revocation windows are small even without a store check.

curl -X POST https://api.example.com/auth/logout-all -H "Authorization: Bearer $TOKEN"

Expected output: The blast radius is bounded.

Troubleshooting

Problem

Revocation not enforced

Solution

Check the version or denylist on every request; trusting expiry alone leaves a window.

Problem

Version store unavailable

Solution

Decide fail-open or fail-closed explicitly; for high-risk actions prefer fail-closed with a short cache.

Limitations

  • Per-request revocation checks add a store lookup unless access tokens are very short-lived.
  • Refresh tokens need their own revocation strategy, usually rotation with reuse detection.

Context

Make it possible to invalidate all of a user sessions at once when a credential may be compromised. A user changes their password or reports a stolen device, but existing JWTs stay valid until they naturally expire, so the attacker keeps access.

Steps

  1. Store a per-user token version or a list of active token families. Expected: The server can invalidate issued tokens.
  2. On logout-everywhere or password change, bump the version or revoke the families. Expected: All outstanding tokens become invalid.
  3. Validate the token version on each request. Expected: Revoked tokens are rejected immediately, not at expiry.
  4. Keep access tokens short-lived so revocation windows are small even without a store check. Expected: The blast radius is bounded.
const user = await users.get(payload.sub);
if (payload.ver !== user.tokenVersion) {
  throw new Unauthorized('token revoked');
}

Verify

  • The server can invalidate issued tokens.
  • All outstanding tokens become invalid.
  • Revoked tokens are rejected immediately, not at expiry.
  • The blast radius is bounded.

Limits

  • Per-request revocation checks add a store lookup unless access tokens are very short-lived.
  • Refresh tokens need their own revocation strategy, usually rotation with reuse detection.