Mastering JWT Security: Complete Developer Guide to Secure Token Authentication
Deep-dive cybersecurity guide to JSON Web Token (JWT) architecture, HS256 vs RS256/ES256, signature verification, and preventing top authentication vulnerabilities.
🛠️ Interactive Tool Available:
Need to inspect, decode, or verify JWT signatures locally without sending corporate tokens to third-party web servers? Use our 100% Client-Side JWT Debugger.
1. Anatomy of a JSON Web Token (RFC 7519)
A JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. A standard JWT consists of three distinct parts separated by dots (.):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsZXgiLCJpYXQiOjE1MTYyMzkwMjJ9.4z_7u_X...
- Header: Specifies the cryptographic algorithm (e.g.
HS256,RS256) and token type. - Payload: Contains claims (user ID, roles, expiration timestamp
exp, issueriss). Important: The payload is Base64URL-encoded, NOT encrypted! Anyone who intercepts the token can read its contents. - Signature: Generated by hashing the encoded Header and Payload with a secret key (symmetric) or private key (asymmetric) to guarantee data integrity.
2. Symmetric (HS256) vs Asymmetric (RS256 / ES256)
Selecting the correct cryptographic algorithm is the first critical decision in JWT architecture:
- HMAC-SHA256 (HS256): Shared Secret. The same secret key is used both to sign and to verify tokens. Best for single monolithic backends where only one trusted service verifies user sessions.
- RSA-SHA256 (RS256) & ECDSA (ES256): Public/Private Keypair. The authentication server signs tokens with a private key, while dozens of microservices or third-party APIs verify tokens using only the public key.
3. The Top 5 JWT Vulnerabilities & How to Prevent Them
Vulnerability #1: The "alg: none" Exploit
In poorly implemented verification libraries, an attacker modifies the token header to {"alg": "none"} and removes the signature part. If the backend accepts unsigned tokens, the attacker gains full administrative access.
Remedy: Explicitly whitelist permitted algorithms in your verification options (e.g. algorithms: ['RS256']) and strictly reject none.
Vulnerability #2: Algorithm Confusion Attack (HMAC vs RSA)
If an auth server expects RS256 but allows dynamic algorithm switching, an attacker can modify the header to HS256 and sign the token using the server's public key (which is public knowledge) as the HMAC secret.
Remedy: Never determine verification logic dynamically from the untrusted token header. Hardcode expected algorithms in your middleware.
Vulnerability #3: Storing JWTs in Insecure LocalStorage
Storing authentication tokens in browser localStorage or sessionStorage makes them vulnerable to cross-site scripting (XSS). Any malicious npm package or injected script can execute localStorage.getItem('token') and exfiltrate credentials.
Remedy: Store session tokens in HttpOnly, Secure, SameSite=Strict cookies that JavaScript cannot read.
4. Secure Node.js & TypeScript Verification Implementation
import jwt from 'jsonwebtoken';
interface UserPayload {
userId: string;
role: 'admin' | 'user';
exp: number;
}
const PUBLIC_KEY = process.env.JWT_PUBLIC_KEY!;
export function verifyAccessToken(token: string): UserPayload {
try {
const decoded = jwt.verify(token, PUBLIC_KEY, {
algorithms: ['RS256'], // Enforce RS256 strictly
issuer: 'https://auth.retrobox.tools',
audience: 'https://api.retrobox.tools',
clockTolerance: 5 // Allow 5s clock skew
}) as UserPayload;
return decoded;
} catch (error) {
if (error instanceof jwt.TokenExpiredError) {
throw new Error('TOKEN_EXPIRED');
}
throw new Error('INVALID_TOKEN_SIGNATURE');
}
}