โก 10-second version
Paste the token at tooladda.online/jwt-debugger.html. Header, payload and claims decoded, expiry checked against the clock, signature verified if you supply the key โ all locally.
โ Important
A JWT is a live credential. Pasting a production access token into a website means handing over whatever that token authorises, for as long as it's valid. Decoding here happens in your browser with no network request โ which is the only acceptable way to debug a real token.
๐ base64url is not encryption โ read your own token right now
The single most consequential misunderstanding about JWTs: the payload is encoded, not encrypted. Anyone holding the token can read every claim inside it without any key at all.
eyJhbGciOiJIUzI1NiJ9 . eyJzdWIiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ . SflKxwRJSMeKKF2QT4f
โโโโโ header โโโโโ โโโโโโโโโโโ payload โโโโโโโโโโโ โโโโโ signature โโโโโ
base64url base64url keyed hash
Base64-decode the middle segment and you get {"sub":"123","role":"admin"} in plain text. The signature stops anyone modifying the token; it does nothing to stop them reading it.
So never put secrets in a JWT payload. No passwords, no card numbers, no internal notes, no PII you wouldn't hand to the client โ because you are handing it to the client.
The two classic JWT attacks
| Attack | How it works | The defence |
|---|---|---|
๐จ alg: none
|
Attacker sets the header to {"alg":"none"}, strips the signature, and edits the payload to "role":"admin". A naive verifier that trusts the header's algorithm accepts it. |
Never read the algorithm from the token. The server decides which algorithm it accepts, and rejects everything else. |
| ๐จ HS/RS confusion | The server verifies RS256 with a public key. The attacker re-signs the token with HS256 using that public key as the HMAC secret. A library that switches mode based on the header validates it happily. | Pin the expected algorithm server-side. Never let the token choose. |
Both attacks exist because the token gets to nominate how it's checked. The audit here flags alg: none, missing exp, an over-long lifetime, and a signature that doesn't verify โ the things worth catching before they ship.
๐งญ How it works
โจ What's inside
| ### โฐ Expiry against the real clock `exp`, `nbf` and `iat` converted to readable local time with a live countdown. "Is my token expired or is my auth broken?" answered in a second. | ### ๐ Real signature verification HS256, RS256, ES256 and PS256 โ paste the secret or the public key and get a definitive valid/invalid, not just a decode. |
| ### ๐จ Security audit Flags `alg: none`, a missing `exp`, suspiciously long lifetimes, and absent `iss`/`aud` โ the checks a code review should catch and often doesn't. | ### ๐งฉ Readable claim breakdown Standard claims explained (`sub`, `aud`, `iss`, `jti`) alongside your custom ones, formatted rather than dumped as one line of JSON. |
๐ ๏ธ Real jobs
| Situation | What you check |
|---|---|
| ๐ 401 from your API | Is it expired, or is the signature wrong? Two different bugs. |
| ๐ "Why is this user unauthorised?" | Read the actual roles and scopes in the payload. |
| ๐ Clock skew across services | Compare iat/exp against your machine's time. |
| ๐ Rotated a signing key | Confirm tokens verify against the new key before deploying. |
| ๐ Learning OAuth2 / OIDC | See what an ID token really contains. |
| ๐ก๏ธ Reviewing someone's auth code | Catch alg: none acceptance and missing expiry before it ships. |
๐ Four steps
1. Open โ tooladda.online/jwt-debugger.html
2. Paste โ the token (use a TEST token if you can)
3. Read โ header, claims, expiry countdown
4. Verify โ paste the secret / public key to check the signature
โถ Decode now โ tooladda.online/jwt-debugger.html
โ ๏ธ Warning
If you have pasted a production token into any online debugger โ including this one โ treat it as exposed and rotate it. Local processing removes the network risk, not the clipboard, screen-share and browser-history risk. Debug with test tokens whenever you can.
โ FAQ
Is my token uploaded?
No. Decoding and verification run in your browser via the Web Crypto API. Check the Network tab โ nothing leaves.
Can anyone read my JWT payload?
Yes. It's base64url-encoded, not encrypted. Any holder of the token can read every claim. Never put secrets in it.
Then what does the signature actually protect?
Integrity and authenticity โ it proves the token wasn't altered and was issued by someone holding the key. It provides no confidentiality.
What is the alg: none attack?
Setting the algorithm to none, dropping the signature, and editing the claims. It works against verifiers that trust the token's own header. Always pin the accepted algorithm server-side.
Should JWTs be stored in localStorage?
It's convenient and exposes the token to any XSS on your page. HttpOnly, Secure, SameSite cookies are generally the safer default for browser sessions.
How do I revoke a JWT?
You largely can't โ that's the trade-off of stateless tokens. Keep lifetimes short, use refresh tokens, and maintain a denylist by jti if you truly need instant revocation.
Can it verify RS256 with a JWK?
Yes โ RS256, ES256 and PS256 verification with a public key, all client-side.
๐ฌ Under the hood
- Decoding and signature verification via the Web Crypto API in vanilla JavaScript โ no upload endpoint exists.
- Supports HS256/384/512, RS256, ES256 and PS256.
- Audit rules target real-world misconfigurations rather than style preferences.
- Works offline once loaded.
Originally published on ToolAdda, where JWT Debugger runs free in your browser โ nothing is uploaded, nothing leaves your device.
Top comments (0)