JSON Web Tokens (JWT) are compact, URL-safe tokens that represent claims between parties. JWTs encode information in JSON format, cryptographically sign it, and optionally encrypt it, enabling stateless authentication and information exchange. Their self-contained nature makes JWTs popular for API authentication, single sign-on, and distributed systems where maintaining server-side session state is impractical.
Structure
JWTs consist of three parts separated by dots: Header, Payload, and Signature.
Header describes the token type (JWT) and signing algorithm (like HMAC SHA256 or RSA). This metadata enables receivers to validate tokens correctly.
Payload contains claims—statements about an entity (typically the user) and additional metadata. Claims include registered claims (standard like iss issuer, exp expiration), public claims (defined in registries), and private claims (custom application-specific).
Signature ensures token integrity. Using the algorithm specified in the header, the signature is created from the encoded header and payload using a secret key or private key. Recipients verify signatures to confirm tokens haven’t been tampered with.
A complete JWT looks like: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Claims
Registered Claims are predefined by JWT specifications. Common ones include:
iss(issuer): who created the tokensub(subject): whom the token is about (typically user ID)aud(audience): who the token is intended forexp(expiration): when the token expires (Unix timestamp)nbf(not before): token isn’t valid before this timeiat(issued at): when the token was createdjti(JWT ID): unique identifier for the token
Custom Claims carry application-specific information: user roles, permissions, email, or any relevant data. Keep payloads small since JWTs are included in every request.
Signing Algorithms
HMAC (HS256, HS384, HS512) uses symmetric keys. The same secret key signs and verifies tokens. This is simple and fast but requires sharing the secret with all verifying parties, limiting its use to trusted environments.
RSA (RS256, RS384, RS512) uses asymmetric cryptography. A private key signs tokens, and a public key verifies them. This enables issuing tokens centrally while distributing public keys for verification, suitable for distributed systems where multiple services verify tokens.
ECDSA (ES256, ES384, ES512) uses elliptic curve cryptography, providing similar security to RSA with smaller keys and signatures, improving performance.
Algorithm Selection matters for security. Never use none algorithm in production (it disables signature verification). Ensure validation rejects tokens with unexpected algorithms to prevent algorithm substitution attacks.
Stateless Authentication
JWTs enable stateless authentication where servers don’t maintain session state. After authentication, servers issue JWTs containing user identity and permissions. Clients include JWTs in subsequent requests, and servers validate signatures and extract claims without database lookups.
This scales horizontally since any server can validate tokens without shared session storage. No sticky sessions or session replication is needed, simplifying load balancing.
The tradeoff is revocation difficulty. Since tokens are self-contained and servers don’t track them, revoking tokens before expiration is challenging.
Token Validation
Proper validation is critical for security. Always verify:
Signature: Confirm the token is signed by a trusted issuer. Invalid signatures indicate tampering or tokens from untrusted sources.
Expiration (exp): Reject expired tokens. Include clock skew tolerance (typically 1-2 minutes) to handle minor time differences between systems.
Not Before (nbf): Reject tokens used before their validity period. This prevents premature token use.
Issuer (iss): Verify tokens come from expected issuers. In multi-tenant systems, this prevents tokens from one tenant being used in another.
Audience (aud): Confirm tokens are intended for your service. Tokens issued for other services shouldn’t be accepted.
Security Considerations
Don’t Store Sensitive Data in JWTs. Payloads are base64-encoded, not encrypted. Anyone can decode and read them. Store only necessary identity and permissions, not passwords or sensitive personal information.
Use Short Expiration Times: Keep token lifetimes short (minutes to hours). If compromised, exposure is limited to the token lifetime. Use refresh tokens for long-term sessions.
Secure Token Storage: Never store JWTs in local storage (vulnerable to XSS attacks). Use HttpOnly, Secure cookies for web applications. For mobile, use platform secure storage.
Validate Thoroughly: Don’t trust tokens blindly. Validate all security-relevant claims. A single skipped check might enable attacks.
Algorithm Confusion: Ensure validation rejects tokens with unexpected algorithms. Attackers might change RSA-signed tokens to HMAC, using the public key as the HMAC secret.
Token Revocation
JWT’s stateless nature complicates revocation. Several strategies address this:
Short Expiration: Keep tokens short-lived. They naturally expire soon, limiting exposure from compromised tokens.
Token Blacklist: Maintain a list of revoked token IDs (jti claim). Before accepting tokens, check they’re not blacklisted. This requires state but provides explicit revocation.
Token Versioning: Include version numbers in user records. Increment versions when revoking all user tokens. Tokens with old versions are rejected, enabling mass revocation (like after password changes).
Refresh Token Rotation: Use short-lived access tokens with refresh tokens. Revoke refresh tokens, preventing new access token issuance while existing access tokens expire naturally.
Best Practices
Use RSA or ECDSA for systems where multiple services validate tokens. This avoids distributing shared secrets.
Always set expiration times. Tokens without exp claims never expire, creating indefinite security exposure if compromised.
Keep payloads small. JWTs are included in every request. Large payloads increase bandwidth and latency.
Use HTTPS always. While JWTs are signed, they should still be protected in transit to prevent theft.
Don’t expose JWTs in URLs. Tokens in URLs appear in logs, browser history, and referer headers. Use POST requests or headers instead.
Rotate signing keys periodically. Even if never compromised, regular rotation limits exposure from undetected breaches.
Validate tokens on every request. Don’t cache validation results; tokens might be revoked or expired since the last check.
Include claims defensively. Add aud, iss, and nbf even if not strictly necessary. These provide additional security validation.
Common Mistakes
Storing Secrets in Tokens: JWTs are not encrypted by default. Don’t include sensitive data.
No Expiration: Tokens without expiration are security risks. Always include exp claims.
Weak Secrets: For HMAC algorithms, use strong, random secrets. Weak secrets enable brute-force attacks.
Ignoring Algorithm: Validate the algorithm claim. Attackers might change algorithms to exploit validation weaknesses.
Trusting User Input: Never create tokens from user-supplied data without validation. Attackers might inject malicious claims.
Local Storage: Storing JWTs in local storage exposes them to XSS. Use HttpOnly cookies instead.
JWE (JSON Web Encryption)
While JWTs are signed, they’re not encrypted by default. For sensitive data, use JWE to encrypt token contents. JWE adds encryption to JWTs, ensuring only intended recipients can read payloads.
However, encrypting tokens adds complexity and performance overhead. Often, simply excluding sensitive data from tokens is simpler and sufficient.
Debugging and Tools
Various tools help work with JWTs. jwt.io provides decoding and verification. Command-line tools parse tokens. Libraries for most languages include JWT support.
However, be cautious decoding JWTs with sensitive data on third-party websites. Use local tools or libraries for production tokens.
When to Use JWT
JWTs work well for stateless authentication in distributed systems, single sign-on scenarios, API authentication, and microservices communication.
Don’t use JWTs when you need immediate revocation (use sessions), when tokens would be very large (use sessions with IDs), or when token theft is especially concerning (use short-lived tokens with refresh token rotation).
JSON Web Tokens provide a powerful mechanism for stateless authentication and secure information exchange. Their self-contained nature enables scalable authentication without server-side session state, while cryptographic signatures ensure integrity. Understanding JWT structure, validation requirements, and security considerations enables using JWTs effectively while avoiding common pitfalls. The key is proper implementation: thorough validation, appropriate expiration times, secure storage, and awareness that JWTs are signed but not encrypted by default. When used correctly, JWTs elegantly solve authentication challenges in modern distributed applications.