This page does two things. It teaches you how JWT attacks work — step by step, on a live token, nothing to install — and it's a fast editor for crafting JWTs once you know how: decode a token, edit either side, re-sign it, and fire off one-click forgeries like alg:none, algorithm confusion and kid injection.
A JSON Web Token (JWT) is the eyJ... string an app hands you after login to remember who you are. If that sentence is new, you're in the right place — start with the walkthrough.
Never seen a JWT before? The walkthrough teaches you one step at a time, and drives the real editor as it goes. Learn mode adds that walkthrough, the explanation on every panel, and a glossary of what each claim means. Turn it off for the bare tool.
Everything runs in your browser. No token, key or secret ever leaves this page — there is no backend here. Only test tokens you are authorised to test.
A JWT is three chunks of base64url text joined by dots. Base64 is encoding, not encryption — anyone holding the token can read every part of it, including you, right now.
When a token comes back, the server recomputes the signature over header.payload using its key, and compares. Match means untampered. Every attack on this page is a way of making that comparison pass when it shouldn't — or making the server skip it entirely.
Paste any JWT here, or use the sample. Green is the header, blue the payload, amber the signature. Type in this box and the decoded JSON below follows; edit the JSON and this box follows.
The same token, decoded. Everything here is editable, and every edit rewrites the box above.
alg tells the server how to verify. kid, if present, tells it which key to fetch. Both arrive from the client, so both are attacker-controlled input.
Edit any claim and the token above rebuilds instantly. With auto re-sign on it is signed with whatever key material you've supplied; with it off you get a tampered token carrying its original, now-wrong signature — which is exactly what you send when you want to know whether the server checks at all.
HS* algorithms sign and verify with the same shared secret — know it and you can mint any token you like. RS/PS/ES sign with a private key and verify with a public one, so forging needs the private half — unless the server can be tricked into using the wrong key, which is what half the attacks below are about.
Tries a built-in list of common JWT secrets against the current HS* token. Add your own below, one per line. For anything serious use hashcat -m 16500.
Each button rewrites the current token in place and logs what it did. Use undo to step back.
None of these break cryptography — they exploit servers that trust the token to describe how it should be checked. Click one, read the log entry it writes underneath, then send the token at your target and watch whether it is accepted. Acceptance is the finding; the tool can't tell you that part.
Make the signature check pass without the key — or skip it altogether. These are the ones that turn into full authentication bypass, so try them first.
The same attack as alg:none in different cases. Blocklists that reject the exact string “none” often still match case-insensitively when choosing the verifier.
The header can name, carry, or link to the key used to verify it. Point any of those at a key you own and the maths still checks out — for the wrong key. Each of these generates a real keypair and signs with it.
Where you'll host the key file. Any host the target can reach works — a VPS, an S3 bucket, a gist, an ngrok tunnel.
kid is a string from the token that the server feeds into a key lookup — a file path, a database query, sometimes a shell command. Ordinary injection, sitting in an authentication header.
Where the impact comes from. These need a token the server already accepts — solve the signature first, then come back and decide who you want to be.
Re-signs the token with HS256 using a known-weak secret. If the app accepts the result, its signing key is guessable and you can mint any token you like.
Faster than cracking when you only want a yes/no: pick the secret the developer probably used and see if the server agrees. The cracker in section 2 tries a longer list.
Drops a classic injection payload into the claim you name, then re-signs.
Claims don't stay in the token — they end up in SQL queries, templates, log lines and lookups. A signed token is a trusted-looking delivery vehicle for all of it.
Every claim in the current payload, with timestamps decoded. Standard claims are explained inline; anything else is the application's own invention — and those are usually the ones that decide what you're allowed to do.
Automatic observations about the token as it stands. [!] is a broken token, [~] is worth attacking, [i] is context.
A JSON Web Token is three base64url-encoded chunks joined by dots: a header naming the algorithm that signed it, a payload of claims about you, and a signature proving a server produced the first two. The header and payload are encoded, not encrypted, so anyone holding the token can read them.
Yes. Decoding needs no key at all, because the header and payload are ordinary base64url-encoded JSON. A key is only needed to verify the signature, or to produce a token the server will accept.
Only if the decoder runs entirely in your browser. This page has no backend, so your token, keys and secrets never leave the tab. Treat any tool that sends tokens to a server as a credential leak, because a JWT usually is one.
The alg field in the header tells the server which algorithm to verify with. Setting it
to none and deleting the signature makes libraries that trust that field skip verification entirely,
which lets you forge any claim you like. Case variants such as None and NONE are worth trying,
because blocklists often miss them.
RS256 signs with a private key and verifies with a public one. If a server picks its verification
function from the token's alg header but passes in the RSA public key it holds, you can
sign a token with HS256 using that public key as the HMAC secret. Public keys are published on
purpose, so this turns public data into a signing key.
HS256, HS384 and HS512 tokens are signed with a shared secret, and cracking is entirely offline: you already hold the signing input and the signature, so candidates can be tested without touching the target. This page tries a built-in list of common secrets; for a real wordlist use hashcat with mode 16500.
The kid header names which key the server should verify with, and servers feed that
string into a file path, a SQL query or sometimes a shell command. That makes it injectable like any
other untrusted input: point it at /dev/null and sign with an empty key, UNION-select a
key you choose, or test it for command injection and SSRF.
Pin the algorithm server-side and reject anything else. Never read alg,
jwk, jku or x5u from the token to decide how to verify it.
Treat kid as an opaque lookup into a fixed key set, never as a path or a query
fragment. Use a random secret of at least 32 bytes for HMAC, validate exp,
nbf, aud and iss on every request, and keep token lifetimes
short.
Luke Stephens, better known as hakluke, is a hacker and entrepreneur, and the founder and CEO of Haksec Group — a group of cybersecurity companies. He built this toolkit.
Haksec Group spans:
Get an email when I publish something new. No spam, ever.