How to Decode a JWT (and What Not to Trust in the Payload)

JWTs are readable by anyone, not just verified by your server. Here is what decoding actually shows you, and the security mistakes it leads to.

A JWT (JSON Web Token) shows up in almost every modern authentication system, usually as a long string with two dots in it, sitting in a cookie or an Authorization header. Decoding one is trivial. Understanding what that decoding does — and doesn't — prove is where most confusion (and a few real vulnerabilities) come from.

What a JWT actually is

A JWT is three Base64URL-encoded segments joined by dots: header.payload.signature.

  • Header — states the algorithm used to sign the token, e.g. HS256 or RS256.
  • Payload — the claims: user ID, expiry (exp), issued-at (iat), roles, and whatever else the issuer put in.
  • Signature — a cryptographic signature over the header and payload, produced with a secret or private key the server holds.

Crucially, the header and payload are encoded, not encrypted. Base64URL is a reversible text encoding, not a cipher. Anyone holding the token — the browser, a proxy, an attacker who intercepts it — can decode the header and payload and read them in plain text without knowing any secret.

What decoding shows you

Paste a token into the JWT Decoder and it splits the token, Base64URL-decodes the header and payload, and shows you the resulting JSON. This is exactly what a server-side JWT library does internally before it even looks at the signature — decoding is a parsing step, not a trust decision.

This is genuinely useful for debugging: confirming which claims an auth provider actually issued, checking an exp timestamp against the current time, or verifying a role claim made it into the token as expected.

What decoding does not prove

This is the part that trips people up: decoding a JWT and reading a valid-looking payload tells you nothing about whether the token is genuine. Anyone can construct a JWT-shaped string with any payload they like — the header and payload are just Base64URL-encoded JSON, easy to fabricate by hand. The only thing that distinguishes a real token from a forged one is the signature, and checking a signature requires the issuer's secret or public key, which a decoding tool in your browser deliberately does not have (and shouldn't — you don't want to paste production signing secrets into a web page).

So: decoding is for reading and debugging. Verifying is a separate, server-side operation performed by whichever backend issued the token, using a JWT library that checks the signature against the secret or public key before trusting anything in the payload.

Common mistakes this leads to

  • Trusting client-decoded claims for authorization. If a frontend decodes its own JWT and shows or hides UI based on a role claim, that's fine for UX — but the backend must independently verify the signature on every request that claim matters for. A user can edit their own token's payload freely; they just can't produce a valid signature for the edited version unless they have the signing key.
  • Assuming "it decoded fine" means "it's valid." A decoder will happily decode an expired, revoked, or entirely fabricated token — decoding never fails due to an invalid signature, because it never checks one.
  • Putting sensitive data in the payload. Since the payload is plainly readable by anyone holding the token, it should never contain passwords, secrets, or anything you wouldn't want visible in a debugger.
  • Ignoring alg: none and algorithm-confusion attacks. Some JWT library misconfigurations historically accepted tokens with no signature at all, or let an attacker switch the expected algorithm. These are server-side verification bugs, not something a decoder can catch — another reason decoding and verifying are different jobs.

The short version

Decoding a JWT is safe, useful, and tells you exactly what claims are inside it. It never tells you whether those claims can be trusted — that requires signature verification with the correct key, performed server-side. Keep those two operations mentally separate and most JWT-related security mistakes disappear.