A JWT (JSON Web Token) shows up in almost every modern API: in the Authorization: Bearer ... header, in session cookies, or in third-party tokens (OAuth, SSO). And yet plenty of people have never actually looked inside one.
The three parts
A JWT is three Base64URL blocks separated by dots: header.payload.signature.
- Header — the signing algorithm (
HS256,RS256...) and the token type. - Payload — the claims: data like
sub(subject),exp(expiration),iat(issued at), and any custom field the backend adds. - Signature — the hash that guarantees the header and payload haven't been modified since signing.
Paste it into the JWT decoder and you'll see the header and payload already parsed into readable JSON, with the expiration date converted to something human instead of a raw Unix timestamp.
Decoding isn't verifying
This is what trips people up most: anyone can decode a JWT, because the header and payload are only Base64URL-encoded, not encrypted. Opening them doesn't require the secret key.
What does require the key (or the public key, for RS256) is verifying the signature — confirming the token hasn't been tampered with and was actually issued by whoever claims to have issued it. An online decoder shows you the contents, but you should never trust someone else's JWT without your backend verifying the signature first.
Why it expires
The exp claim is an expiration date in seconds since the Unix epoch. If your session "logs itself out" every so often, this is almost always why: the token expired and the client didn't refresh it in time. Compare it with the Unix timestamp converter if you need to do the math by hand.
When to distrust a token
- If the header's
algisnone— it means the issuer isn't signing anything, a classic vulnerability if the backend doesn't explicitly reject it. - If there's no
exp— the token never expires, which is rarely intentional. - If the payload carries sensitive data in plain sight (passwords, card numbers) — a JWT isn't an encrypted container, it shouldn't hold anything that can't be seen.
The short version: use the decoder to debug and understand, but real JWT validation always goes through your server.

