1. The Anatomy of a JWT & The 'alg: none' Exploit

A JSON Web Token consists of three distinct Base64URL-encoded segments separated by periods: Header.Payload.Signature. The header defines metadata about the token, including the signing algorithm ({"alg": "HS256", "typ": "JWT"}). The payload contains declared claims about the user or session ({"sub": "user_102", "role": "member", "exp": 1718000000}). The signature is generated by hashing the header and payload with a secret or private key.
In early JWT specifications, the RFC permitted an unsigned algorithm token designated as "alg": "none" for testing and debugging environments. Vulnerable JWT libraries respected this header without verifying application configuration. An attacker can intercept any valid token, change "alg": "HS256" to "alg": "none", alter the payload claims to {"role": "superadmin"}, strip the signature entirely, and submit the modified token. If the server does not enforce a strict algorithm allowlist, it accepts the unverified token as valid, granting the attacker complete administrative control.
Modern authentication architectures must explicitly disallow none and reject any token lacking a valid cryptographic signature. Learn more about secure API architecture in our Cybersecurity Best Practices Guide and verify your endpoints using the WeSecureX Vulnerabilities Catalog.
// Forged alg: none JWT Token Example
// Header: {"alg":"none","typ":"JWT"} -> eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0
// Payload: {"sub":"admin","role":"superuser"} -> eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJzdXBlcnVzZXIifQ
// Signature: (empty)
const forgedToken = "eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJzdXBlcnVzZXIifQ.";
// SECURE VERIFICATION IN NODE.JS (jsonwebtoken)
import jwt from 'jsonwebtoken';
export function verifyUserToken(token: string, publicKey: string) {
// CRITICAL: Explicitly specify permitted algorithms!
return jwt.verify(token, publicKey, {
algorithms: ['RS256'], // Rejects 'none' and 'HS256' automatically
issuer: 'https://auth.example.com',
audience: 'https://api.example.com'
});
}2. Algorithm Confusion Attacks: RSA vs. HMAC (CVE-2015-9235)

One of the most insidious architectural flaws in JWT authentication is the Algorithm Confusion (or Key Confusion) Attack. Many organizations adopt asymmetric cryptography (RS256), where the authentication server signs tokens using a private RSA key, and decentralized microservices verify tokens using a publicly distributed public key (frequently published at /.well-known/jwks.json).
In a key confusion attack, the adversary downloads your public RSA key. They construct a forged JWT payload declaring "role": "admin", but modify the header from "alg": "RS256" to symmetric "alg": "HS256" (HMAC-SHA256). The attacker then signs the token using your public RSA key as the HMAC shared secret. If the backend verification library passes the public key string into a generic jwt.verify(token, key) function without pinning the algorithm, the library treats the public key as an HMAC secret string. Because the attacker signed the token using that exact string, the signature verification check passes with 100% mathematical validity!
To neutralize key confusion attacks, verification logic must never allow the token header to dictate which cryptographic verification method is invoked. Always enforce an explicit algorithm allowlist pinning verification strictly to RS256 or ES256. Verify your security headers and transport security with the Security Headers Checker.
| Algorithm Type | Signing Key | Verification Key | Security Recommendation |
|---|---|---|---|
| RS256 / ES256 | Private Key (Kept strictly on auth server) | Public Key (Distributed to verification microservices) | Recommended: Immune to secret leakage across distributed services |
| HS256 | Symmetric Shared Secret (256-bit min) | Identical Shared Secret | Acceptable only in monolithic apps; vulnerable if secret is brute-forced |
| none | None | None | Prohibited: Completely disables authentication integrity |
3. Token Storage: HttpOnly Cookies vs. LocalStorage

Where you store authentication tokens on the client defines your vulnerability profile against web attacks. Single Page Applications (SPAs) frequently store JWTs in browser localStorage or sessionStorage. While this makes tokens easy to access via JavaScript for API calls, it exposes your application to catastrophic credential theft: any Cross-Site Scripting (XSS) vulnerability anywhere on the domain allows an attacker to execute localStorage.getItem('token') and exfiltrate credentials instantly.
To protect session credentials, store access and refresh tokens in HttpOnly, Secure, SameSite=Strict cookies. Because HttpOnly cookies are completely inaccessible to client-side JavaScript APIs, an XSS attacker cannot extract or clone the token. Combine this with short access token lifetimes (5 to 15 minutes) and rotating refresh tokens stored in secure database tables. When an access token expires, the client calls /api/auth/refresh, which validates the refresh token, invalidates the old token, and issues a new pair.
Audit your web application's susceptibility to script injection and token theft using the WeSecureX XSS Scanner and run complete perimeter scans with the Website Security Scanner.
// Secure Cookie-Based JWT Issuance in Next.js / Express
export function setAuthCookies(res: Response, accessToken: string, refreshToken: string) {
// Access Token: Short-lived (15 minutes)
res.cookie('access_token', accessToken, {
httpOnly: true, // Blocks JavaScript access (XSS immune)
secure: true, // Enforces encrypted HTTPS transmission
sameSite: 'strict', // Blocks cross-origin transmission (CSRF defense)
path: '/api',
maxAge: 15 * 60 * 1000 // 15 minutes
});
// Refresh Token: Bound strictly to the token refresh endpoint
res.cookie('refresh_token', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
path: '/api/auth/refresh',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 days
});
}Apply it with WeSecureX
Add a hostname you own or are allowed to test, run a scan, and open the findings for that target. A confirmed result includes the request WeSecureX sent and the response the site returned, so you can reproduce it, fix it in your own application, and rescan the same host to confirm the issue is gone. WeSecureX is automated testing, not a manual penetration test, and a clean report is not a promise that every weakness is gone.
WeSecureX modules for this topic
Checks that belong with this topic
- Explicitly enforce accepted algorithms in verification options (e.g., algorithms: ['RS256']).
- Reject tokens with alg: none or invalid cryptographic signatures.
- Store sensitive authentication tokens in HttpOnly, Secure, SameSite=Strict cookies.
- Set short access token lifespans (5 to 15 minutes) and implement refresh token rotation.
- Scan application endpoints with WeSecureX XSS and Security Header tools.
Actionable Checklist
WeSecureX Platform · Surface Monitor
Application Attack Surface Analyzer
Inspect open ports, TLS certificate chains, HTTP headers, and API endpoint security posture.
Includes: TLS/SSL cipher suite & expiration monitoring · Security header verification (CSP, HSTS) · Subdomain asset discovery
Frequently Asked Questions
Because JWTs are stateless, instant revocation requires either maintaining a distributed Redis denylist of revoked `jti` (JWT ID) claims, maintaining a user token version counter in the database, or keeping token lifetimes very short (e.g., 5 minutes) so that revoking the refresh token limits exposure window.
No! JWT payloads are Base64URL-encoded, not encrypted. Anyone who intercepts or views the token can decode and read all payload claims in plaintext. For confidential data, use JSON Web Encryption (JWE) or keep sensitive data server-side.
The [WeSecureX Vulnerability Catalog](/vulnerabilities) and [Security Scanner](/scanner) inspect API responses, headers, and authentication flows for insecure cookie flags and token exposure.
Authoritative Sources & References
- RFC 7519: JSON Web Token (JWT)IETF (official)View Source
- OWASP JSON Web Token Cheat Sheet for JavaOWASP (technical)View Source
Related Guides
Continue exploring related technical architecture and defensive guides
CSRF · cookies
Cross-Site Request Forgery (CSRF): SameSite Cookies & Anti-CSRF Token Defense
Learn how to completely prevent Cross-Site Request Forgery (CSRF) vulnerabilities using modern browser security primitives, SameSite cookies, and cryptographically secure tokens.
HTTPS · SSL/TLS
HTTPS Mixed Content: Passive vs. Active Insecure Resources & Complete Fix Guide
A complete guide to auditing, identifying, and resolving HTTPS mixed content issues that destroy browser padlock trust and trigger security warnings.
subdomain takeover · DNS security
Subdomain Takeover: Detection, Exploitation & Prevention Guide
A developer and DevOps guide to discovering and eliminating dangling DNS records and preventing high-severity subdomain takeover exploits across cloud infrastructure.