System Design Cases
JWT Best Practices: Algorithms, Rotation, Revocation, Storage
JWT Best Practices: signing algorithms (RS256 over HS256 for multi-service), key rotation via kid header and JWKS, short-lived access + rotating refresh tokens, audience and exp/nbf validation, jti for revocation via Redis blocklist, alg-confusion attacks (alg=none, RS256->HS256 swap), and storage trade-offs (HttpOnly cookies vs localStorage XSS). 5 animated scenarios plus an embedded ADR comparing JWT vs opaque tokens with introspection.
JWT best practices: validation profiles, rotation, and browser boundaries
A JWT is a token format, not an authentication or authorization decision by itself. Each token kind has an exclusive validation profile, trusted key source, intended audience, lifetime, and replay or revocation policy.
Security invariants
- JWT-C1: JWT is a representation format; applications define mutually exclusive validation profiles for each token kind.
- JWT-C2: Verifiers configure an algorithm allowlist and bind each key to one algorithm instead of trusting the token header to choose verification.
- JWT-C3: Validation includes exact trusted issuer, intended audience, required claims, expiry, not-before, and bounded skew in addition to signature verification.
- JWT-C4: Trusted issuer metadata controls JWKS retrieval; untrusted jku or x5u values from the token do not choose network destinations or keys.
- JWT-C5: Signed JWT payloads are not confidential, and browser storage controls do not eliminate same-origin XSS actions.
- JWT-C6: Short access-token lifetime, current authorization checks, refresh rotation, reuse detection, and incident revocation solve different freshness and replay problems.
Trust-boundary map
| Component | Responsibility |
|---|---|
browser | Browser |
client | Client or Backend for Frontend |
issuer | Trusted Token Issuer |
jwks | Pinned Issuer JWKS |
gateway | JWT Validation Gateway |
api | Protected API |
revocation-state | Session and Revocation State |
refresh-service | Refresh Token Family Store |
audit-log | Validation Audit |
attacker | Token Thief |
Topology edges represent authenticated or otherwise explicit communication paths. Responses reuse those physical paths in reverse; no response-only or bypass edges are added.
Executable scenarios
issue-and-validate — Issue and validate under one token profile
The verifier fixes the expected token type and algorithm set, resolves keys from the configured issuer, validates required claims, then applies current authorization state.
algorithm-confusion-rejection — Reject algorithm confusion
The verifier uses a server-configured algorithm allowlist and a key bound to that algorithm; the token header cannot select none or switch asymmetric and symmetric verification.
issuer-audience-time — Validate issuer, audience, and time claims
A valid signature is insufficient when issuer, audience, expiry, not-before, or required token-profile claims do not match.
cross-jwt-confusion — Keep token kinds mutually exclusive
ID Tokens, access tokens, logout tokens, and internal session tokens use distinct typ values, claims, keys or audiences so one kind cannot substitute for another.
signing-key-rotation — Rotate signing keys with bounded overlap
The issuer publishes a new trusted key before use, retains the old verification key only while unexpired tokens require it, then removes it according to policy.
untrusted-key-url-rejection — Reject token-controlled key locations
A jku or x5u header is untrusted input. The verifier never lets the token choose a network destination; kid can only select within the issuer key set configured by trusted metadata.
browser-token-theft — Model browser token exposure
JWT payloads are merely encoded when signed. Browser storage choice changes exposure, while XSS can still perform same-origin actions even when an HttpOnly cookie hides the session value.
authorization-freshness — Short lifetime does not replace authorization
A token that has not expired may outlive a role removal; sensitive APIs combine token validation with current session or authorization state.
refresh-family-reuse — Rotate refresh tokens and detect reuse
A refresh token is a high-value credential stored separately from access tokens; reuse of an invalidated family member triggers containment.
Operational and failure rules
- Every rejection path fails closed at the component that owns the decision; infrastructure failure is never converted into authentication, authorization, or integrity success.
- Retries preserve stable transaction identity, replay detection, bounded freshness, and audit context. A retry does not erase a prior success or compromise signal.
- Concurrent validation branches are independent checks. Completion requires every mandatory branch, and no check substitutes for another.
- Logs contain decision metadata and stable identifiers, not credentials, bearer tokens, cryptographic keys, or sensitive payloads.