JWT Attack Playground

Learn how JSON Web Tokens get broken — by forging the attacks yourself and firing them at a configurable verifier. Every byte of crypto runs in your browser.

🔒 100% client-side · nothing leaves your browser · works offline
1

Decode & inspect

Paste any JWT. It's decoded locally — the header, payload, and claims never leave your browser.

Token segments
Paste a token above to decode it.
Header
Payload
Verify signature

Check whether the pasted token's signature is actually valid — using the algorithm from its own header. HS256 takes a secret; RS256/ES256/PS256 take the matching public key PEM.

Paste a token and a key, then verify.
2

Attack modules

Each module forges a token from the payload in step 1 (or its own inputs), explains the server-side flaw it abuses, and — for the live attacks — lets you fire it at the verifier in step 3.

alg: none — strip the signature

live

The JWS spec defines an alg of none: an unsigned token with an empty signature. If a server trusts the header, it accepts a token anyone can mint. Naive denylists that block "none" often miss case variants.

Why it works: the server reads alg from attacker-controlled data and skips verification when it says none.
Forged token
Click “Forge unsigned token”.
Defense: pin the accepted algorithm(s) server-side and never derive it from the token. Explicitly reject none.

Algorithm confusion — RS256 → HS256

live

An RS256 server verifies with an RSA public key — which is, by definition, public. If the verifier trusts the header's alg, an attacker switches it to HS256 and signs with HMAC using the public key bytes as the secret. The server, holding that same public key, HMAC-verifies successfully.

Why it works: one key blob is trusted for any algorithm. The public key is secret enough to verify RS256, but as an HMAC key it also lets an attacker sign.
Forged token — key without trailing newline
Paste a public key and forge.
Forged token — key with trailing newline
Paste a public key and forge.

Two variants because the server's stored key file may or may not end in a newline — that one byte changes the HMAC. Try both against the verifier.

The same trick works with an EC (ES256) public key — the forge HMACs whatever public-key bytes you paste, so paste an EC PUBLIC KEY PEM too.

Defense: pin the algorithm to RS256. Use separate key types per algorithm. Modern libraries require you to declare algorithms: ['RS256'].

jwk header injection — self-signed key

live

A JWS header may carry its own verification key in a jwk field. If the server verifies against that embedded key instead of a key it controls, an attacker generates their own keypair, embeds the public key in the header, and signs with the matching private key. It verifies — because the attacker supplied both halves.

Why it works: the server trusts a key it found inside the token it is trying to authenticate — so the token vouches for itself.
Forged token (embeds a fresh public key)
Pick an algorithm and forge.
Embedded public JWK (in the header)
Defense: never resolve the verification key from the token. Ignore jwk/jku/x5c, or restrict them to a pinned, server-side allowlist.

Weak-secret brute-force (HS256)

live

HS256 tokens are only as strong as their secret. This runs a ~10,000-entry wordlist of common secrets against the token's signature — entirely in a background thread in your browser.

Why it works: a guessable secret means anyone can compute a valid signature. Once cracked, forged tokens are indistinguishable from legitimate ones — no verifier setting can tell them apart.
Defense: use a long, random, high-entropy secret (≥256 bits) — or asymmetric keys (RS256/ES256) so there's no shared secret to guess.

Claim tampering — edit & re-sign

live

Change any claim (say "role":"admin") and re-sign with a key you control or have cracked. If the server's key is weak/leaked, or it doesn't verify at all, the tampered token sails through.

Tampered token
Edit the payload and re-sign.
Defense: keep secrets secret and strong; never trust client-supplied claims for authorization without server-side validation.

kid header injection

advanced

The kid (key ID) header tells the server which key to load. If the server uses it unsanitised, an attacker can point it at a file whose contents they control or can predict — e.g. path traversal to an empty/known file (kid: "../../../../dev/null" → empty key) — or SQL-inject the key lookup to return a chosen value. Then they sign with that known key.

Why it works: kid is attacker-controlled input used to select a secret, without validation.

Live demo: forge an HS256 token whose kid traverses to /dev/null, signed with an empty secret — what a vulnerable server would then read and verify against.

Forged token
Click to forge.
Defense: treat kid as an opaque lookup into an allowlist of known keys; never use it as a file path or SQL parameter.

jku / x5u URL abuse

advanced

jku (JWK Set URL) and x5u (X.509 cert URL) headers tell the server where to fetch the verification key. If the server fetches from an attacker-controlled or SSRF-reachable URL, the attacker hosts their own public key there, signs with the matching private key, and the token verifies.

Why it works: the server trusts a key location supplied inside the very token it's trying to authenticate.

Explain-only here — a live demo would require a network fetch, which this tool deliberately never makes. The forged header simply looks like: {"alg":"RS256","jku":"https://attacker.example/jwks.json","kid":"1"}.

Defense: ignore jku/x5u, or restrict them to a strict allowlist of trusted hosts; pin your JWKS endpoint server-side.
3

Simulated verifier

A pretend server that verifies a token. Configure it vulnerable or secure, then fire a forged token at it. It models the common footgun: a library that picks the algorithm from the token's own header.

“Send to verifier” fills this automatically to match each attack.

Server policy
No token verified yet.