JWT Deep Dive
Also Known As
JWT
JSON Web Token
JWS
JWE
Bearer token
TL;DR
JSON Web Tokens carry signed (or encrypted) claims — three Base64url-encoded sections: header.payload.signature. Security depends entirely on algorithm choice and verification correctness.
Explanation
JWT structure: header (algorithm + type), payload (claims: sub, exp, iat, iss, custom), signature (HMAC-SHA256 or RSA/ECDSA). Signed JWTs (JWS) prevent tampering but the payload is readable by anyone. Encrypted JWTs (JWE) also hide the payload. Critical security: always validate exp (expiry), iss (issuer), aud (audience). Never accept algorithm=none. Prefer RS256 (asymmetric) for public verification over HS256 (shared secret). Store in HttpOnly cookies, not localStorage.
Common Misconception
✗ A valid JWT signature means the token is trustworthy — a signature is only valid relative to a key; if the algorithm is none or the key is weak, the signature provides no security.
Why It Matters
JWT algorithm confusion (accepting none or RS→HS algorithm switching) is a critical vulnerability that has affected many frameworks — understanding JWT security prevents this entire class of auth bypass.
Common Mistakes
- Not validating exp claim — expired tokens accepted indefinitely after logout.
- Accepting algorithm: none — allows unsigned tokens; always whitelist accepted algorithms explicitly.
- Algorithm confusion: RS256 → HS256 — attacker signs with public key as HMAC secret; validate alg header.
- JWT in localStorage — XSS-accessible; use HttpOnly cookies with SameSite=Strict.
Avoid When
- You need to invalidate tokens before expiry — JWTs are stateless and cannot be revoked without a server-side denylist.
- The payload contains sensitive data — JWT payloads are base64-encoded, not encrypted; anyone can decode them.
- Using the alg:none vulnerability window — always validate the algorithm header and reject none.
- Long-lived JWTs — a stolen token is valid until expiry; keep access tokens short (15 min) and use refresh tokens.
When To Use
- Stateless authentication across multiple services where a shared session store is not feasible.
- API authentication where the client stores the token and sends it with each request.
- Single sign-on (SSO) flows where identity is delegated from an auth server to resource servers.
- Short-lived service-to-service tokens where the overhead of a token introspection call is undesirable.
Code Examples
✗ Vulnerable
// Algorithm confusion vulnerability:
function validateJwt(string $token, string $publicKey): array {
$parts = explode('.', $token);
$header = json_decode(base64_decode($parts[0]), true);
$alg = $header['alg']; // Attacker sets alg=HS256
// Uses public key as HMAC secret — attacker can sign!
return verifySignature($token, $publicKey, $alg);
}
✓ Fixed
// Whitelist algorithm, validate all claims:
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// Always specify allowed algorithms explicitly:
$decoded = JWT::decode(
$token,
new Key($publicKey, 'RS256') // Algorithm whitelist — rejects HS256, none
);
// Validate critical claims:
if ($decoded->iss !== 'https://auth.example.com') throw new Exception('Invalid issuer');
if ($decoded->aud !== 'api.example.com') throw new Exception('Invalid audience');
if ($decoded->exp < time()) throw new Exception('Token expired');
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
25 Mar 2026
Views
37
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Amazonbot 11
Perplexity 9
Unknown AI 3
Ahrefs 3
Google 2
SEMrush 2
Majestic 1
Also referenced
How they use it
crawler 30
pre-tracking 1
Related categories
⚡
DEV INTEL
Tools & Severity
🟠 High
⚙ Fix effort: Medium
⚡ Quick Fix
Always verify the algorithm explicitly (do not trust the 'alg' header), validate exp/iat/iss/aud claims, and use a vetted library — never decode and trust without verification
📦 Applies To
PHP 7.0+
web
api
🔗 Prerequisites
🔍 Detection Hints
base64_decode on JWT without signature verification; accepting alg:none; no exp claim validation
Auto-detectable:
✓ Yes
semgrep
psalm
⚠ Related Problems
🤖 AI Agent
Confidence: Medium
False Positives: Medium
✗ Manual fix
Fix: Medium
Context: File
Tests: Update
CWE-347
CWE-345