The most consequential misunderstanding about JSON Web Tokens is that they are encrypted. They are not. A JWT is signed, which is a different guarantee entirely, and confusing the two leads directly to leaking data you assumed was hidden.
Three segments, separated by dots
The header says which algorithm signed the token and, often, which key was used. The payload holds the claims — who the token is about, who issued it, when it expires, and whatever else the issuing system chose to include. The signature is computed over the first two segments using a secret or private key.
The header and payload are Base64url encoded, not encrypted. Anyone holding the token can decode them instantly, without any key, which is exactly what a decoder does. Encoding is for safe transport, not secrecy.
What the signature proves
The signature proves the token has not been altered since it was issued, and that it was issued by someone holding the key. That is all. It does not hide the contents, it does not prove the token is still valid, and it does not prove the token has not been stolen and replayed by someone else.
Which is why alg: none is dangerous. It declares the token unsigned, and any system that accepts such a token is trusting data an attacker can freely rewrite. Reject it explicitly rather than relying on a library's defaults.
Expiry, and what it doesn't cover
exp is a Unix timestamp in seconds, and a token past it must be rejected. nbf does the reverse, marking a token as not yet usable. Both are worth checking explicitly rather than assuming the library did it.
Neither covers revocation. A token issued for a week remains cryptographically valid for a week even if the user logs out, changes their password, or is deleted. If you need to revoke early, you need server-side state — a deny list or short-lived tokens with refresh — because the token itself cannot tell you.
In short
Never put anything sensitive in a JWT payload; assume it is public. Check expiry yourself, reject alg: none explicitly, and remember that a valid signature says nothing about whether the token should still be honoured.
JWT Decoder
Decode a JSON Web Token, read its claims, check expiry, and verify HS, RS or ES signatures — without the token ever leaving your browser.
Keep reading
UUID v4 vs v7: which one belongs in your database?
Random UUIDs scatter writes across an index. Time-ordered v7 fixes that, at the cost of revealing creation time — how to choose between them.
What makes a password strong (it isn't the symbols)
Why length beats complexity, what entropy in bits actually measures, and why the old advice about special characters made passwords worse.
MD5, SHA-1, SHA-256: which hash should you actually use?
What it means for a hash to be broken, why fast hashes are the wrong tool for passwords, and how to verify a downloaded file properly.