5/16/2026
JWT Authentication Bypass
JSON Web Tokens (JWTs) have become the de facto standard for modern authentication. They are stateless, scalable, and easy to use. But with great power comes great responsibility—and a handful of critical pitfalls.
How Attackers Crack Your Stateless Fortress
JSON Web Tokens (JWTs) have become the de facto standard for modern authentication. They are stateless, scalable, and easy to use. But with great power comes great responsibility—and a handful of critical pitfalls.
If you’ve ever implemented JWT authentication, you know the feeling: you issue a token, verify the signature, and trust the user’s identity. But what if an attacker can forge that trust without ever stealing a password?
In this post, we’ll explore real-world JWT authentication bypass techniques. These aren’t theoretical edge cases; they’ve breached major production systems. Let’s dive into the dark side of the token.
1. The "None" Algorithm Attack
This is the classic, the legend, the facepalm of JWT history. The JWT specification allows an algorithm called none. When this algorithm is used, the signature is not validated. Yes, you read that correctly—no signature at all.
How it works:
A normal JWT has three parts: header.payload.signature. The header typically looks like this:
json
{
"alg": "HS256",
"typ": "JWT"
}
An attacker changes it to:
json
{
"alg": "none",
"typ": "JWT"
}
Then they remove the signature part entirely, leaving header.payload. (with a trailing dot).
Bypass example:
Original token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4ifQ.abc123
Modified token: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyIjoiYWRtaW4ifQ.
If the server accepts none algorithm, it will skip signature verification and trust the payload. Congratulations, you’re now admin.
Why this happens:
Libraries that follow the spec blindly, or developers who forget to disable none in production. Some older libraries even defaulted to allowing it.
Mitigation: Never accept alg: none. Explicitly reject it.
2. Algorithm Confusion (RS256 to HS256)
This is a beautiful cryptographic mismatch. JWTs support both symmetric (HS256) and asymmetric (RS256) signing. The problem? The algorithm is specified in the header, but the verification key type is often hardcoded.
How it works:
Server expects tokens signed with RS256 (private/public key pair).
It verifies using a public key.
Attacker changes header to HS256 (symmetric HMAC).
Now the server uses the same public key as the HMAC secret.
Wait—what? The server takes the public key (which is often exposed via .well-known/jwks.json or simply guessable) and treats it like a shared secret. The attacker can then sign a token using that public key as the HMAC secret.
Step by step bypass:
Fetch the public key from the server (e.g., https://example.com/.well-known/jwks.json).
Convert it to the appropriate format (PEM to raw bytes).
Create a malicious payload: {"user": "admin", "iat": now}.
Sign the token using HS256 with the public key as the secret.
Send it to the server. Server sees alg: HS256, tries to verify with what it thinks is a symmetric secret—but that secret is actually its own public key. Verification passes.
Real impact:
This has broken major frameworks. The fix? Always validate that the algorithm matches the key type. Or better, reject tokens with alg mismatches.
3. Kid Injection & Path Traversal
The kid (Key ID) header parameter is used to tell the server which key to use for verification. If the server blindly trusts kid and fetches the key from a filesystem, database, or external URL, things get dangerous.
Attacks:
Path Traversal:
json
{
"alg": "HS256",
"kid": "../../../../dev/null"
}
If the server does read_file("/var/keys/" + kid), an attacker can read arbitrary files. Worse, if the server uses the contents of that file as the verification key, they can control the secret.
SQL Injection:
json
{
"kid": "1' UNION SELECT 'known_secret' --"
}
If the server queries a DB like SELECT key FROM keys WHERE id = '1' ... — injection can return an attacker-controlled secret.
Command Injection:
Some older systems used wget or curl based on kid to fetch remote JWKs. That’s a remote code execution nightmare.
Mitigation: Never trust kid as input. Use a whitelist of valid key IDs. Don’t embed filesystem or database logic directly.
4. Weak Signature Brute-Force (HS256)
When developers use HS256 (symmetric), the security relies entirely on the secrecy and entropy of the signing key. Too often, I see keys like secret, password123, or change_me.
Bypass technique:
If you have a valid token (even for a low-privilege user), you can try to brute-force the secret offline.
Capture one JWT.
Use hashcat (mode 16500) or jwt_tool to crack.
Common wordlists crack these in seconds.
Once you have the secret, you can sign any token you want. You are God.
Mitigation: Use a 32+ byte cryptographically random secret. Rotate keys periodically.
5. JWKS Injection & Server-Side Request Forgery (SSRF)
Some JWT libraries support the jku (JWK Set URL) header. This tells the server: “Hey, go fetch my public key from this URL over there!”
Attack:
Attacker controls a remote server with a malicious JWKS.
json
{
"alg": "RS256",
"jku": "https://attacker.com/my-keys.json"
}
They sign the token using their own private key and host the corresponding public key at that URL. The server fetches the key and—if no whitelist or validation exists—accepts the token.
Even worse, the jku URL can point to internal services (e.g., http://169.254.169.254/latest/meta-data/). If the server fetches it, you have an SSRF that leaks cloud metadata.
Mitigation: Disable jku and jks unless absolutely required. If needed, whitelist exact, trusted URLs. Never follow redirects automatically.
6. Timestamp Manipulation (Time-Based Bypass)
JWTs contain exp (expiration), nbf (not before), and iat (issued at) claims. These are critical for session validity. But what if the server’s clock is wrong? Or if the validation logic is flawed?
Common bypasses:
Set exp to a very large number like 9999999999 (year 2286). If the server doesn’t reject absurd values, the token never expires.
Set nbf to the past. Or remove nbf entirely if the check is optional.
Floating-point rounding issues: some libraries in PHP or JavaScript have had bugs where exp = 0 or exp = null passes validation.
Real example:
A server checks if ($token->exp < time()). What if exp is not an integer but a string? Type juggling in some languages causes "0" < time() to be false, bypassing expiration.
Mitigation: Validate data types strictly. Reject tokens with malformed timestamps. Enforce maximum reasonable exp values.
7. Claim Injection via Parameter Pollution
This is less about crypto and more about logic. JWT payloads are JSON. But what if your application merges JWT claims with user-supplied input from a different source (like a POST body or URL param)?
Example vulnerable code (pseudo):
python
user_id = request.POST.get('user_id') or jwt_payload.get('sub')
if is_admin(jwt_payload):
allow_access()
If the POST parameter user_id overrides the JWT’s sub claim, an attacker could send a valid low-privilege token but add a POST param user_id=1 (admin). The logic picks the param over the token.
Mitigation: Never mix untrusted input with JWT claims. Pick one source of truth (the token) and ignore others.
The Defensive Checklist
After reading these bypass techniques, you might be sweating. Don’t worry—defense is possible.
Reject alg: none explicitly in your JWT library configuration.
Enforce algorithm whitelisting – only allow HS256 or RS256, never both from the same endpoint without key type validation.
Validate kid – use a whitelist, never filesystem or DB interpolation.
Disable jku, jks, and remote JWKS fetching unless you have strict URL whitelists.
Use short expiration times (15-30 minutes) and refresh tokens.
Keep secrets strong – 32+ random bytes, stored in secrets management.
Upgrade your JWT library – many of these bugs are fixed in recent versions.
Log and monitor for weird alg or kid values.
Final Thoughts
JWT is a powerful tool, but it’s also a footgun. The beauty of stateless authentication is also its danger: a single forged token can compromise your entire system without touching your database.
The bypass techniques above have been found in Uber, Google (yes, early JWT libraries), and countless startups. Don’t let your app be the next case study.
Want to test your own JWTs? Grab jwt_tool or Burp JWT Editor and try these attacks yourself—ethically, of course.
Stay safe, and never trust the alg field.