Token & JWT Misconfiguration
Token & JWT Misconfiguration at a glance
Overview
JSON Web Tokens (JWT) are a popular standard for representing claims securely between parties, commonly used for authentication in modern web applications and APIs. However, improper implementation can lead to critical security vulnerabilities.
Common JWT vulnerabilities include accepting the 'none' algorithm allowing unsigned tokens, algorithm confusion attacks where RS256 tokens are validated as HS256 using the public key as a secret, missing or incomplete validation of claims like expiration and issuer, storing sensitive data in JWT payloads (which are only base64 encoded, not encrypted), and insecure token storage exposing tokens to XSS attacks.
Where it occurs
JWT vulnerabilities occur in token handling where algorithms, claims, or signatures aren’t properly validated, secrets are weak or exposed, or tokens lack expiration, revocation, or secure storage.
Impact
JWT misconfigurations lead to authentication bypass through forged tokens, session hijacking from stolen tokens, privilege escalation by modifying claims, unauthorized API access, data exposure from token payloads, and inability to revoke compromised tokens.
Prevention
Prevent this by using RS256/ES256 (reject “none”), verifying signatures first, validating exp/iat/nbf/iss/aud, keeping tokens short-lived with rotating refresh tokens, storing in HttpOnly Secure cookies, omitting sensitive payloads, and enabling revocation.
Examples
Switch tabs to view language/framework variants.
JWT verification vulnerable to algorithm confusion attack
JWT library doesn't enforce algorithm, allowing RS256 to HS256 downgrade.
const jwt = require('jsonwebtoken');
const fs = require('fs');
const publicKey = fs.readFileSync('public.pem');
app.use((req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
// BUG: No algorithm specified
const decoded = jwt.verify(token, publicKey);
req.user = decoded;
next();
});- Line 9: No algorithm specified
Not specifying algorithm allows attackers to switch from RS256 to HS256.
const jwt = require('jsonwebtoken');
const fs = require('fs');
const publicKey = fs.readFileSync('public.pem');
app.use((req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
try {
// Enforce RS256 algorithm
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256']
});
req.user = decoded;
next();
} catch (err) {
return res.status(401).json({ error: 'Invalid token' });
}
});- Line 11: Enforce expected algorithm
Always specify expected algorithm in verification options.
Engineer Checklist
-
Use RS256 or ES256 for production (not HS256 with shared secrets)
-
Explicitly reject the 'none' algorithm
-
Validate signature before processing any claims
-
Verify exp (expiration) claim and reject expired tokens
-
Validate iss (issuer) matches expected value
-
Validate aud (audience) matches your application
-
Use short token lifetimes (15 min access, longer refresh)
-
Store tokens in HttpOnly, Secure, SameSite cookies
-
Never store sensitive data in JWT payloads
-
Implement token rotation for refresh tokens
-
Use cryptographically strong signing secrets (256+ bits)
-
Implement token revocation mechanism
-
Log and monitor for token anomalies
End-to-End Example
An application using JWT authentication accepts the 'none' algorithm, allowing attackers to forge valid tokens without any signature.
// Vulnerable: Accepts any algorithm including 'none'
const decoded = jwt.verify(token, publicKey);// Secure: Explicitly specify allowed algorithms
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'], // Only allow RS256
issuer: 'https://your-app.com',
audience: 'your-api',
clockTolerance: 0
});Discovery
Decode a JWT and check the 'alg' field. Try changing it to 'none' and removing the signature. Test if the application accepts it.
-
1. Test JWT algorithm confusion
httpAction
Change RS256 JWT to HS256 with public key as secret
Request
GET https://api.example.com/protectedBody:"Authorization: Bearer <modified_jwt>"
Response
Status: 200Body:{ "note": "Modified JWT accepted, signature bypassed" }Artifacts
algorithm_confusion signature_bypass -
2. Test JWT with none algorithm
httpAction
Send JWT with alg=none
Request
GET https://api.example.com/protectedBody:"Authorization: Bearer eyJ...none..."
Response
Status: 200Body:{ "note": "Unsigned JWT accepted" }Artifacts
none_algorithm no_signature_verification -
3. Test JWT expiration validation
httpAction
Send expired JWT
Request
GET https://api.example.com/protectedBody:"Authorization: Bearer <expired_jwt>"
Response
Status: 200Body:{ "note": "Expired token still accepted" }Artifacts
no_expiration_check token_reuse
Exploit steps
Attacker modifies the algorithm field to 'none' or exploits algorithm confusion to forge tokens with elevated privileges.
-
1. Forge JWT using algorithm confusion
RS256 to HS256 attack
httpAction
Sign JWT with public key using HS256
Request
GET https://api.example.com/adminBody:"Authorization: Bearer <forged_jwt>"
Response
Status: 200Body:{ "note": "Admin access granted with forged token" }Artifacts
forged_jwt privilege_escalation admin_access -
2. Escalate privileges by modifying JWT claims
JWT claims manipulation
httpAction
Change role claim to admin in JWT
Request
GET https://api.example.com/protectedBody:"{...,'role':'admin',...}"Response
Status: 200Body:{ "note": "Modified claims accepted, admin privileges granted" }Artifacts
privilege_escalation modified_claims -
3. Bypass authentication with none algorithm
Unsigned JWT attack
httpAction
Remove signature and set alg to none
Request
GET https://api.example.com/user/123Body:"Authorization: Bearer eyJ...none..."
Response
Status: 200Body:{ "note": "Full API access without valid signature" }Artifacts
authentication_bypass unsigned_token_accepted
Specific Impact
Complete authentication bypass allowing attackers to impersonate any user, access protected resources, and perform privileged operations without valid credentials.
Fix
Always specify the allowed algorithms explicitly to prevent algorithm confusion and 'none' algorithm attacks. Validate issuer, audience, and other claims. Use asymmetric algorithms (RS256, ES256) for better key management in distributed systems.
Detect This Vulnerability in Your Code
Sourcery automatically identifies token & jwt misconfiguration vulnerabilities and many other security issues in your codebase.
Scan Your Code for Free