If you've ever worked with auth, you've seen a JWT — a long string like eyJhbGci... split into three parts by dots. It looks cryptic, but it's surprisingly simple once you see inside.
A JWT has three parts
header.payload.signature
-
Header – tells you the signing algorithm, e.g.
{"alg":"HS256","typ":"JWT"} -
Payload – the claims (the actual data), e.g.
{"sub":"123","name":"John","iat":1516239022} - Signature – verifies the token wasn't tampered with (needs the secret/key)
The header and payload are just Base64url-encoded JSON — not encrypted. That means anyone can read them. So:
⚠️ Never put secrets in a JWT payload. It's signed, not hidden.
Decoding one yourself
You can decode the payload in the browser console:
const [, payload] = token.split(".");
console.log(JSON.parse(atob(payload)));
Or, if you just want to paste a token and instantly see the header + payload (without sending it to a server), I built a free decoder that runs entirely in your browser: https://forgly.dev/tools/jwt-decoder
Decoding ≠ verifying
Reading a JWT is trivial. Trusting it is not — you must verify the signature on your server with the secret/public key before relying on any claim. Decoding just lets you inspect what's there.
That's the whole mental model: a JWT is a readable, signed envelope — not a locked box.
Top comments (0)