JWT decoder with security check and claim glossary

JSON Web Token (JWT) decoder that runs in your browser. Flags what's off with your token: alg: none, expired, weak HS256 secret, PII in the payload.

A JWT (JSON Web Token) is a signed data packet in three parts: header, payload, signature. Reading one isn't a hack, since header and payload are base64url, not encryption. What's usually more interesting than the contents is what's wrong with the token: expired, alg: none, an email in the payload, a weak HS256 secret. You see those flags above the payload here, before you start digging through claims yourself.

Your token never leaves your browser. No upload, no logging.
Sample tokens

Ready for your token.

Paste anything above and we decode the header and payload, run eight common pitfall checks, and explain the common standard claims.

Runs entirely in your browser. Your token isn't uploaded, stored, or analysed. Not in the URL either.

What's actually inside your JWT?

A signed JWT in JWS compact form has three segments separated by dots: header, payload, and signature. Header and payload are base64url-encoded JSON objects - readable without a key, broken out above with coloured underlines on the pasted token (cyan, violet, coral). Encrypted JWTs in JWE compact form have five segments; those aren't accepted here on purpose.

The header almost always carries the signing algorithm (alg), the token type (typ, almost always JWT), and optionally a key ID (kid) so the receiver can pick the matching public key from its JWKS. The payload carries the actual claims - the seven standard ones registered in RFC 7519 §4.1, plus one common extension:

  • sub - the subject, usually a user ID. Stable across logins, not human-readable.
  • iss - the issuer, who minted the token. Trust starts here.
  • aud - the audience, who the token is for. Your API checks that it's in the list.
  • iat / exp / nbf - timestamps in Unix seconds: issued at, expires at, not before.
  • jti - a unique token ID, useful for revocation lists.
  • scope - OAuth permissions, often space-separated. Not in RFC 7519 itself, but later registered in IANA's JWT Claims registry via RFC 8693.

These claims plus azp (an OIDC claim) and the common header fields (alg, typ, kid) get a small ? chip - hover or tap for the one-sentence definition with its spec section. For iat, exp, and nbf, the Unix timestamp renders alongside a UTC datetime + relative phrase (in 4m 12s or 4m 12s ago), so you don't have to switch tabs for the conversion.

You don't need the secret to decode a JWT

The header and payload of a JWT are base64url-encoded, not encrypted. Reading them only needs the token itself - no secret, no public key. A key is only relevant if you want to verify the signature, i.e. confirm the token actually came from the issuer it claims and wasn't tampered with on the way.

Many decoders still ask for the key the moment you paste a token. That keeps the myth alive that you can't see the contents without a secret - and trains the reflex to drop a real key into a foreign input field.

Here it works the other way around: reading is the default view, signature verification sits below in a closed disclosure and stays that way until you actively open it. Only then does the key field appear. That matches the most common workflow: grab a token from a network tab or a log, peek at the contents, done. The signature is the server's concern, not yours.

If you do want to verify, HS256/384/512 (shared secret), RS256/384/512 and PS256/384/512 (RSA with a PEM public key), and ES256/384/512 (elliptic curve) all run through your browser's Web Crypto API. alg: none stays unsupported on purpose - the pitfall check above flags it, and verification would just be theatre.

alg: none is not a joke - and your decoder doesn't warn you

alg: none is a valid JWT header value: no algorithm, no signature. The JWT spec allows it because integrity can, in some setups, be secured by the enclosing data structure (RFC 7519 §6). A library that accepts alg: none blindly lets every payload mutation slip through - the classic auth bypass.

The attack pattern is trivial:

  1. Rewrite alg in the header from RS256 to none.
  2. Set sub in the payload to admin (or whichever claim the server uses for authorisation).
  3. Drop the signature - third segment, empty string.
  4. Send it. If the server accepts what the header claims rather than checking against an explicit allowlist, the token goes through.

RFC 8725 (the JWT BCP) has said the same thing since 2020: implementations should accept only algorithms on an explicit allowlist, never reading it from the header. The bug keeps coming back anyway. CVE-2026-23993 (HarbourJwt) is the latest example: the verification path accepted unrecognised alg values (including none) without filtering them. The same "unknown alg" bypass shape keeps showing up in different libraries year after year.

The status pill above marks alg: none in red the moment the header declares it - whether you want to verify or not, you see it. Seven of seven competitors we audited don't flag this; they show the decoded header and leave the interpretation to you. If you fished the token out of a log, that's a security check you'd otherwise miss.

Production token in a web tool? Four questions first

Jamie Tanna's argument against online tooling roughly goes: "We're teaching people to blindly trust arbitrary websites that they don't have any relationship with." For a JWT the risk is concrete: dropping a real production access token into a foreign browser tool is potentially a data leak. Either because the tool sends the token to a server (it happens), because the tool puts it in the URL (it happens), or because the browser history-syncs it to your other devices (it happens).

Three rules this decoder holds itself to, against exactly that:

  1. Your token never leaves your browser. No upload, no logging, no server round-trip.
  2. The token never lands in the URL - not while typing, not on share. There's intentionally no "Share token" button.
  3. If the token looks like production (email in the payload, UUID-shaped values, long exp, known issuer like *.auth0.com or accounts.google.com), opening the signature-verify disclosure shows a nudge: "Looks like a production token. Sure?". One click dismisses it - but the question got asked.

Four questions worth running through yourself before pasting a real token:

  1. Do I actually need the production token? For local debugging, a test token from the dev issuer is usually enough.
  2. Who runs the tool? Toolflux is a small solo project from Germany. No backend, no data pipeline, everything runs in your browser. Imprint and contact in the footer.
  3. Is the token stored anywhere? Here, no - not in the URL, not in browser storage, not in server logs (there's no server endpoint that sees it).
  4. If something goes wrong: can I rotate the token? If the answer is "no, that's a long-lived refresh token with admin scope", that token doesn't belong in a web tool.

Frequently Asked Questions

What do sub, aud, iss mean in a JWT?

sub (Subject) is the ID of whoever the token is about, usually a user ID. aud (Audience) is who the token is for: your API server checks that it's in that list. iss (Issuer) is who minted the token, the auth server. Trust starts at iss. Each of these claims carries a ? chip in the decoder with the definition and spec section.

Do I need the secret to decode a JWT?

No. The header and payload are just base64url, not encryption. Reading them only needs the token itself. You need the secret or public key only to verify the signature.

What is alg: none and why is it dangerous?

alg: none is a valid JWT header value: no algorithm, no signature. Servers that blindly trust whatever the header claims let arbitrary payload mutations slip through. The status pill above marks alg: none in red whenever the header declares it.

Is my JWT stored anywhere?

No. The whole decoder runs in your browser - your token isn't uploaded, isn't persisted in the URL, isn't logged anywhere.

What's the difference between HS256 and RS256?

HS256 (HMAC-SHA256) is symmetric: sender and receiver share the same secret. RS256 (RSA-SHA256) is asymmetric: only the issuer signs with their private key, anyone verifies with the public key. RS256 is the right choice as soon as more than one service has to accept the token.