| name | aidd-jwt-security |
| description | JWT security review patterns. Use when reviewing or implementing authentication code, token handling, session management, or when JWT is mentioned. |
JWT Security Review
AVOID JWT if you can. Prefer opaque tokens with server-side sessions.
Patterns {
Session State
any(refresh token rotation, refresh reuse detection, jti denylist, jti revocation,
token bound to session, token bound to device, logout invalidates token server-side)
=> Critical: Prefer opaque tokens with server-side sessions. You're tracking state anyway.
Storage & Transport
(token in localStorage or sessionStorage) => Critical: XSS vulnerable. Use httpOnly Secure SameSite=Strict cookies.
(token in URL or query params) => Critical: Leaks via logs, Referer, browser history, analytics.
(token logged or sent to analytics) => Critical: Scrub tokens from all logging pipelines.
(SameSite=None or missing CSRF protection) => Critical: CSRF exposure. Use SameSite=Strict or add CSRF tokens.
Algorithm & Signature
(JWT 'none' algorithm) => Critical: Signature bypass. Reject unsigned tokens.
(JWT verification disabled) => Critical: Always verify signatures.
(jwt.decode without verify) => Critical: Use jwt.verify().
(alg from token used to select verification) => Critical: Alg confusion. Strict allowlist + key type must match algorithm.
(HS256 or symmetric algorithm) => Critical: Use asymmetric algorithms (RS256/ES256).
Verification Failure Handling
(verification failure allows anonymous access) => Critical: Fail closed. Invalid token = no access.
(verification failure allows partial or degraded access) => Critical: Fail closed. Invalid token = no access.
Token Purpose
(ID token used as access token) => Critical: Wrong token type. Use access tokens (typ: at+jwt) for API auth.
(typ header not validated) => Critical: Reject tokens without expected typ. Prevents token confusion.
Key Handling
(kid used to fetch key from untrusted source) => Critical: SSRF/key injection. Allowlist kid values.
(JWKS URL derived from iss without strict allowlist) => Critical: Attacker-controlled keys. Pin JWKS URLs.
(JWKS endpoint not pinned or cached) => Warn: Cache JWKS with TTL. Validate kid against known set.
(multi-issuer: verification keys shared across issuers) => Critical: Issuer key isolation required. One keyset per issuer.