JWT decoder and signature verifier
Decode a JSON Web Token’s header and payload and verify HS256/HS384/HS512 signatures against a known secret - all locally.
Open in ctfpalA JWT is three Base64-URL segments joined by dots: header, payload, signature. The first two are not encrypted - anyone holding the token can read the claims. The signature is the only thing standing between a user and an admin claim, which is why every JWT challenge is really a question about how the signature is checked.
Read the header first
The header names the algorithm, and that name is the attack surface. alg: HS256 means a shared secret - crackable if it is weak. alg: RS256 means a public key - and an implementation that lets you switch it to HS256 will verify the signature using the public key as an HMAC secret, which you already have. alg: none means no verification at all.
| Header field | What it enables |
|---|---|
alg | Algorithm confusion, none bypass |
kid | Path traversal or SQL injection into key lookup |
jku / x5u | Point key retrieval at a server you control |
typ | Rarely checked; occasionally a filter bypass |
Worked example
A standard HS256 token
Input
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ3Vlc3QiLCJhZG1pbiI6ZmFsc2V9.7vN1kUnJ3nHfP_3Xf2X8sXJ7lPMlN3SfResult
Header {"alg":"HS256","typ":"JWT"}, payload {"user":"guest","admin":false}The `admin: false` claim is readable and, without signature verification, editable.
Load this example in the workspaceCommon questions
- Can I edit a JWT payload?
- You can always edit it; whether the server accepts it depends on signature verification. That is exactly what the [none-algorithm](/tools/jwt-none-algorithm) and [secret brute force](/tools/jwt-secret-bruteforce) pages are about.
Part of a module
6. Web attacks and session tokens
Read and forge JWTs and Flask sessions, find content nobody linked to, and probe for injection with detection payloads.
Practise on real challenges
Go deeper
- Attacking JWTs: alg=none, algorithm confusion, and the header fields nobody auditsA JSON Web Token is a signed claim you were handed and asked to give back. Every classic JWT bug is a place where the verifier lets the token choose how it is verified - alg=none, RS256 to HS256 confusion, kid injection, and attacker-hosted key URLs.
Related tools
JWT alg=none bypass generator
Forge an unsigned JWT by setting the algorithm to none, and understand why some libraries still accept it.
JWT secret brute force
Recover a weak HMAC signing secret from a JWT by testing a wordlist against the token’s own signature, in the browser.
Base64 decoder and encoder
Decode and encode Base64 and Base64-URL in the browser, with padding repair and automatic detection of nested encodings. Nothing is uploaded.
Flask session cookie decoder
Decode and verify Flask’s itsdangerous session cookies, with automatic zlib detection and both key-derivation schemes.