TL;DR
JWTs are commonly used for authentication but easy to implement wrong. The main vulnerabilities are: accepting the "none" algorithm, using weak secrets that can be brute-forced, and algorithm confusion attacks. Always specify the allowed algorithm explicitly and use a strong secret (256+ bits for HS256).
Common JWT Vulnerabilities
1. Algorithm Confusion
Some libraries accept the algorithm from the token header instead of enforcing one. Attackers can switch from RS256 to HS256 and sign with the public key.
// VULNERABLE: doesn't specify algorithm
jwt.verify(token, publicKey);
// Attacker changes header to HS256 and signs with public key
// { "alg": "HS256" } + HMAC(payload, publicKey)
2. None Algorithm
Old or misconfigured libraries accept alg: "none" which skips signature verification entirely.
// Attacker sends:
// Header: { "alg": "none" }
// Payload: { "sub": "admin", "role": "admin" }
// Signature: (empty)
// Bad library accepts it as valid!
3. Weak Secrets
Short or common secrets can be brute-forced. Tools like hashcat can crack weak JWT secrets quickly.
Weak secrets: "secret", "password123", or any string under 32 characters can be cracked. Use at least 256 bits of randomness for HS256.
Secure JWT Implementation
import jwt from 'jsonwebtoken';
// Always specify the algorithm explicitly
const decoded = jwt.verify(token, process.env.JWT_SECRET, {
algorithms: ['HS256'], // Reject any other algorithm
issuer: 'yourapp.com',
audience: 'yourapp.com'
});
// Generate a strong secret (run once, save to env)
// node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Should I use HS256 or RS256?
HS256 (symmetric) is simpler for single services. RS256 (asymmetric) is better when multiple services verify tokens, as you can share the public key without exposing the private key.
How do I handle JWT expiration?
Use short-lived access tokens (15 min to 1 hour) with refresh tokens. Always check the exp claim and reject expired tokens.
Should I store JWTs in localStorage?
LocalStorage is vulnerable to XSS. Consider HttpOnly cookies for web apps. For SPAs, weigh the tradeoffs carefully based on your XSS risk.