JWT Analyzer & Tester
Decode · Audit · Brute-Force · Forge · Attack Simulation · History
Python / PyJWT
Web Crypto API
Pen-Test Ready
Sample Tokens
CRITICAL
alg:none Bypass
Algorithm "none" — skips signature check entirely
CRITICAL
Weak HS256 Secret ("secret")
Top-1 in every brute-force wordlist
CRITICAL
Sensitive Data in Payload
Password + credit card stored in plaintext
CRITICAL
kid Injection Attack
SQL injection in key ID header
WARNING
Expired + Minimal Claims
No iss/aud/jti, expired token
GOOD
Well-formed RS256
Asymmetric, all claims, 15-min expiry
Paste JWT

Token Structure
Paste a token above…

Decoded Claims
🔍
Header · Payload · Signature appear here

Verify Signature (HMAC)
Security Findings
🛡️
Analyze a token to see findings,
score, timestamps and Python fix
Header Claims
Payload Claims

Sign With (HMAC)

Quick Presets
Generated Token
Token appears here after generation…

Preview
⚗️
Generate a token to preview it
Known JWT Attack Vectors
CRITICAL alg:none Signature Bypass
Set alg:"none" — vulnerable libraries skip verification entirely. Attacker can forge any payload including privilege escalation. CVE pattern: jwt.decode(token, options={"verify_signature":False})
CRITICAL Algorithm Confusion (RS256→HS256)
If a server accepts both RS256 and HS256, attacker uses the public key (which is public!) as the HMAC secret. Server verifies with public key — it matches. Fix: never list both in one algorithms=[] allowlist.
CRITICAL kid Header Injection
kid: "../../dev/null" → empty key → trivial sign
kid: "x' UNION SELECT 'secret'--" → SQL injection
Validate kid strictly: re.match(r'^[a-zA-Z0-9\-_]{1,64}$', kid)
WARNING Weak Secret Brute-Force
Anyone with a JWT can run offline brute-force. hashcat tests billions/sec. Common secrets crack in milliseconds. The demo token uses "secret" — send to Analyzer to crack it instantly.
WARNING Replay Attack (no jti / no exp)
Without jti + server denylist, stolen tokens are valid until expiry. Even after logout. Fix: jti on every token + Redis denylist on logout.
WARNING Privilege Escalation via Payload Tampering
If signature verification is skipped or misconfigured, Base64-decode payload, change role:"user"role:"admin", re-encode and submit. Never trust payload claims without verifying the signature.
Attack Demo Output
💀
Click "Demo →" to generate an attack token

Python Defence Template
🐍 Secure PyJWT Validation
import jwt, re from jwt.exceptions import DecodeError, ExpiredSignatureError # NEVER disable verification: # jwt.decode(token, options={"verify_signature": False}) ← BAD def safe_decode(token: str) -> dict: return jwt.decode( token, public_key_or_secret, algorithms=["RS256"], # exact list — never wildcard audience="myapp-api", issuer="https://auth.myapp.com", options={ "require": ["exp","iss","aud","jti","sub"], "verify_exp": True, } ) # Sanitize kid BEFORE using it to look up keys: def safe_kid(kid: str) -> str: if not re.match(r'^[a-zA-Z0-9\-_]{1,64}$', kid): raise ValueError("Invalid kid") return kid # Denylist check (run after decode): def check_revoked(payload: dict): if redis.exists(f"revoked:{payload['jti']}"): raise PermissionError("Token revoked")
Analyzed Token History
📜
Tokens you analyze appear here.
Click any entry to reload it.