Skip to main content
High

JWT Attack (JSON Web Token)

CategoryAuthentication & AccessOWASPA07:2021 – Identification and Authentication FailuresFirst seen2015Read time9 minVerified2026-03-10
DEFINITION

A JWT attack exploits vulnerabilities in JSON Web Token implementation to bypass authentication, escalate privileges, or impersonate users. Common attacks include algorithm confusion (setting 'alg': 'none'), weak signature verification, token manipulation, and exploiting token reuse across services. JWTs are widely used in modern APIs and SPAs, making these attacks particularly impactful.

How JWT Attack (JSON Web Token) Works

JWT attacks target the token lifecycle: creation, transmission, verification, and storage. The token structure (header.payload.signature) contains sensitive claims but is often improperly validated. Attackers manipulate tokens to change user roles, extend expiration, forge signatures, or bypass verification entirely. Unlike session cookies managed server-side, JWTs are stateless — once issued, the server must validate them without database lookup, increasing the risk of implementation errors.

1

Analyze JWT implementation

Identify how tokens are generated, transmitted, and validated. Check for weak secrets (dictionary words, short keys), insecure algorithms (none, HS256 when RS256 expected), missing claim validations (exp, iat, nbf), and token reuse across different security contexts.

2

Exploit weak verification

If the server doesn't verify the signature properly, attackers can forge tokens. Test by removing the signature entirely (set 'alg': 'none') or by signing with weak or stolen secrets. Some libraries accept tokens without signature verification if the algorithm is explicitly set to 'none'.

3

Manipulate token claims

If tokens are signed with a weak or known secret, decode and modify claims to elevate privileges. Common targets: 'role' (admin), 'sub' (user ID), 'exp' (expiration), or custom claims that control access. Re-sign with the compromised secret and submit to the application.

4

Exploit algorithm confusion

Some JWT libraries allow the attacker to specify the signing algorithm. Attackers change 'alg' from RS256 (public key) to HS256 (symmetric), tricking the server into using the public key as the symmetric signing key. This allows token forgery without the private key.

Real-World Examples

2018

Critical vulnerability in popular JWT libraries

Security researchers discovered algorithm confusion vulnerabilities in multiple JWT libraries across different languages. The vulnerability allowed attackers to bypass signature verification by changing the algorithm header from RS256 to HS256. This affected thousands of applications, including enterprise systems and financial platforms using vulnerable library versions.

2021

SaaS platform privilege escalation via weak JWT secret

A SaaS platform used a default weak JWT secret for development that was accidentally deployed to production. Attackers discovered the secret through exposed environment variables, generated admin tokens, and gained access to all customer data. The breach exposed over 50,000 user records and resulted in a $2.3 million fine under GDPR.

2022

JWT none algorithm bypass in microservices architecture

A company's microservices architecture used JWT for inter-service authentication. Due to a misconfiguration, the verification service accepted tokens with 'alg': 'none', allowing attackers to bypass authentication entirely. Attackers accessed internal APIs, exfiltrated customer data, and disrupted service for 4 hours before detection.

Impact & Risk Assessment

JWT attacks enable complete account takeover, privilege escalation to administrative access, and unauthorized access to protected APIs. In stateless architectures, compromised tokens are difficult to revoke quickly. Attackers can access multiple systems if tokens are reused across services. Impact includes data breaches, financial fraud, service disruption, and compliance violations (GDPR, HIPAA, PCI DSS). Stateful systems with session management can invalidate sessions instantly; JWT-based systems require token blocklists or short expiration periods, increasing complexity and potential for errors.

How to Detect JWT Attack (JSON Web Token)

Monitor for suspicious JWT-related patterns: tokens with 'alg': 'none', unusually long or short tokens, tokens with invalid signatures, expired tokens being accepted, or claims mismatching expected formats. Log all JWT verification failures with full token metadata (excluding secrets). Implement anomaly detection on claim values (unexpected role changes, impossible expiration dates). Use static analysis to detect vulnerable JWT libraries or unsafe verification patterns in code. Monitor for token reuse across different IP addresses or user agents indicating token theft.

How to Prevent JWT Attack (JSON Web Token)

Use strong, cryptographically random secrets (minimum 256 bits for HS256, 2048+ bits for RSA). Never use the 'none' algorithm in production. Always verify the signature before using any claims. Validate all critical claims: expiration (exp), not-before (nbf), issued-at (iat), issuer (iss), audience (aud), and subject (sub). Use versioning for token schemas to detect incompatible changes. Implement short token lifetimes (15-30 minutes for access tokens) with refresh tokens stored securely. Use token rotation to mitigate token reuse. Implement proper algorithm whitelisting in verification libraries. Regularly audit dependencies for known JWT vulnerabilities. Consider stateful JWT (adding jti claim and maintaining server-side blocklist) for critical operations.

Code Examples

Vulnerable: Weak Secret and No Algorithm Check
import jwt

# VULNERABLE: Weak secret and accepts any algorithm
SECRET = 'my-secret-key' # Dictionary word, weak!

def create_token(user_id, role):
return jwt.encode(
{'user_id': user_id, 'role': role},
SECRET,
algorithm='HS256'
)

def verify_token(token):
try:
return jwt.decode(token, SECRET, algorithms=['HS256', 'none'])
# ^ Accepts 'none' algorithm - vulnerable!
except jwt.InvalidTokenError:
return None

# Attacker can forge token by changing alg to 'none'
# and modifying role to 'admin'
Secure: Proper JWT Implementation
import jwt
from datetime import datetime, timedelta
import os

# SECURE: Strong secret from environment
SECRET = os.getenv('JWT_SECRET')
if not SECRET or len(SECRET) < 32:
raise ValueError('JWT_SECRET must be at least 32 characters')

def create_token(user_id, role):
payload = {
'user_id': user_id,
'role': role,
'iat': datetime.utcnow(),
'exp': datetime.utcnow() + timedelta(minutes=15), # Short-lived
'iss': 'myapp.com', # Issuer validation
'aud': 'myapp-api' # Audience validation
}
return jwt.encode(payload, SECRET, algorithm='HS256')

def verify_token(token):
try:
payload = jwt.decode(
token,
SECRET,
algorithms=['HS256'], # Only accept HS256
issuer='myapp.com',
audience='myapp-api',
options={'require': ['exp', 'iat', 'iss', 'aud']}
)

# Additional business logic validation
if payload.get('role') not in ['user', 'admin']:
raise jwt.InvalidTokenError('Invalid role')

return payload
except jwt.ExpiredSignatureError:
raise ValueError('Token has expired')
except jwt.InvalidTokenError as e:
raise ValueError(f'Invalid token: {str(e)}')
Secure: JWT Middleware with Rotation (Node.js)
const jwt = require('jsonwebtoken');
const crypto = require('crypto');

const JWT_SECRET = process.env.JWT_SECRET;
const TOKEN_VERSION = 'v1';

// Token blocklist (in production, use Redis)
const tokenBlocklist = new Set();

function createAccessToken(userId, role) {
return jwt.sign(
{
userId,
role,
version: TOKEN_VERSION,
type: 'access'
},
JWT_SECRET,
{
algorithm: 'HS256',
expiresIn: '15m',
issuer: 'myapp.com',
audience: 'myapp-api',
subject: userId.toString()
}
);
}

function createRefreshToken(userId) {
return jwt.sign(
{ userId, version: TOKEN_VERSION, type: 'refresh' },
JWT_SECRET,
{ algorithm: 'HS256', expiresIn: '7d' }
);
}

function verifyToken(token, expectedType = 'access') {
try {
const decoded = jwt.verify(token, JWT_SECRET, {
algorithms: ['HS256'],
issuer: 'myapp.com',
audience: 'myapp-api'
});

// Check if token is in blocklist
const jti = decoded.jti;
if (tokenBlocklist.has(jti)) {
throw new Error('Token has been revoked');
}

// Validate token type
if (decoded.type !== expectedType) {
throw new Error('Invalid token type');
}

// Check version for rotation
if (decoded.version !== TOKEN_VERSION) {
throw new Error('Token version outdated');
}

return decoded;
} catch (error) {
throw new Error(`Token verification failed: ${error.message}`);
}
}

// Revoke a token (e.g., on logout)
function revokeToken(token) {
const decoded = jwt.decode(token);
tokenBlocklist.add(decoded.jti);
}

Strengthen your defenses against JWT Attack (JSON Web Token) with PowerWAF.

Comprehensive web application security with WAF, rate limiting, and real-time threat monitoring.

Free plan spots are limited

Frequently Asked Questions

Session-based authentication stores session IDs on the server (database, Redis) and requires a lookup for each request. JWTs are self-contained tokens that include all claims and are verified cryptographically without server-side storage. JWTs are stateless and scale better but are harder to revoke and more vulnerable to implementation errors. Sessions provide easier revocation but require state management infrastructure.
No, strong secrets don't prevent algorithm confusion attacks, missing signature verification, or weak claim validation. Proper defense requires multiple layers: strong secrets, algorithm whitelisting, signature verification, claim validation, short expiration, and secure library usage. Each layer addresses different attack vectors.
Yes, 'alg': 'none' removes signature verification, allowing anyone to forge tokens. The 'none' algorithm is intended only for debugging and development, never production. Some legitimate use cases exist for unauthenticated claims, but these should use separate mechanisms, not JWT with 'none'. Always reject tokens with 'alg': 'none' in production.