DEV Community

Mubeen Khan
Mubeen Khan

Posted on

Your JWT is not encrypted: what every developer should know before pasting tokens into a debugger

A JSON Web Token looks like gibberish. Three long strings separated by dots, something like eyJhbGciOi.... It feels secret. It is not.

Base64URL is an encoding, not encryption. Anyone who holds your token can decode the first two parts in seconds and read everything inside: who it was issued to, when it was issued, when it expires, and every custom claim your app stuffed in there. If you ever put something sensitive in a JWT payload because it "looked encrypted," that data was never hidden at all.

What is actually inside a token

A JWT has exactly three parts:

  1. Header: the signing algorithm and token type, usually {"alg":"HS256","typ":"JWT"}.
  2. Payload: the claims. Standard ones include sub (who the token is for), iat (issued at), nbf (not valid before) and exp (expires at). All three time claims are Unix timestamps.
  3. Signature: a cryptographic stamp over the first two parts. It proves the token was not altered. It does not hide anything.

Decoding shows you the header and payload. Verifying proves the signature matches a trusted key. Those are two different jobs, and confusing them is how bugs happen.

The two checks that matter most

Expiry. The exp claim is a Unix timestamp for the moment the token stops being valid. A token with no exp never expires on its own. If you are debugging an auth failure, the first thing to check is whether exp is in the past, and whether nbf is in the future. Most "random" auth failures are just one of those two.

The algorithm. If the header says alg is none, the token is unsigned. No signature protects it at all. Servers that accept none tokens by mistake let anyone forge a token, and this has caused real breaches. Any decoder worth using should flag alg: none loudly instead of quietly showing you the payload.

Decode it yourself, without sending it anywhere

You can inspect a token without uploading it to a server. I built a free JWT decoder that runs entirely in your browser: paste a token and it shows the header and payload as formatted JSON, renders every time claim as a readable date, labels the token valid, expired or not yet valid, and flags alg: none and missing-expiry risks. Try it here: https://www.theutilityhub.online/tools/jwt-decoder

It never uploads, stores or logs your token. Even so, prefer a test token over a live production token. A production JWT is a credential, and the safest place for one is nowhere except the server that issued it.

One last rule of thumb: if you would not print it on a t-shirt, do not put it in a JWT payload. Decoding takes seconds, and everyone holding the token can do it.

Top comments (0)