JSON Web Token (JWT)
A JWT is a signed, URL-safe token with header, payload, and signature. It carries claims but is not encrypted by default, and verification must pin algorithms and validate claims.
Definition
A JSON Web Token is a compact token format defined by RFC 7519. It consists of three base64url segments: a header describing the algorithm and type, a payload containing claims, and a signature over the first two segments. The signature lets a holder verify integrity and authenticity with a shared secret or public key. The payload is readable by anyone who possesses the token; JWT provides signing, not confidentiality, unless nested encryption is used.
Context and scope
JWTs are used for stateless access tokens, service-to-service authentication, and short-lived authorization claims. They are a poor fit for long-lived sessions that need immediate revocation unless a server-side denylist or short expiry with refresh rotation is added. The token is only as safe as the code that verifies it and the client that stores it.
Common misconceptions
- JWT payloads are encrypted — they are base64url-encoded and readable; do not put secrets in claims
- Verifying the signature is enough — expiration, issuer, audience, and algorithm must also be validated
- Any JWT library defaults are safe — some accept the algorithm named in the token header, enabling algorithm-confusion attacks
Anti-patterns
- Accepting the `none` algorithm or trusting the header's algorithm without an allowlist
- Storing long-lived JWTs in localStorage where XSS can read them
- Using JWTs as session IDs without revocation or rotation
Related concepts
Related examples
Authoritative source
Structure
header.payload.signature
The header and payload are base64url-encoded JSON. The signature is computed over header.payload using the declared algorithm and a key. Anyone can decode the first two segments; only the verifier can validate the signature.
Verify, do not just decode
import jwt from 'jsonwebtoken';
const claims = jwt.verify(token, publicKey, {
algorithms: ['RS256'],
issuer: 'https://auth.example.com',
audience: 'https://api.example.com',
});
Decoding without verification is useful for debugging, never for authorization. Pin the accepted algorithms, validate exp, nbf, iss, and aud, and reject tokens whose key ID is unknown.
When to use
Use short-lived JWTs for stateless access tokens and service identity. For browser sessions, prefer HttpOnly, Secure, SameSite cookies over localStorage, and pair access tokens with refresh rotation or a server-side revocation mechanism. Compared to opaque session IDs, JWTs avoid a database lookup per request but make immediate revocation harder.
Pitfalls
Never put passwords, personal data, or secrets in claims. Treat kid as untrusted input and resolve it through a controlled key set. Clock skew can invalidate fresh tokens or accept expired ones; define a small tolerance. A JWT is not a substitute for authorization checks on each resource.