If you have worked with modern APIs, you have carried a JSON Web Token: a long, three-part string separated by dots, usually arriving in an Authorization: Bearer … header. JWTs (RFC 7519, pronounced “jot” by the specification’s authors and “the thing that keeps logging me out” by everyone else) are a standard way to package a set of claims — “this is user 42, an admin, until Tuesday” — so that any service can verify them without calling back to the issuer. This guide explains what is inside, how the security actually works, and where JWT implementations go wrong.
The three segments
A JWT looks like this (illustrative example, shortened):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiI0MiIsIm5hbWUiOiJBZGEiLCJpYXQiOjE3MDAwMDAwMDB9.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJVadQssw5c
Each segment is Base64URL-encoded (the URL-safe Base64 variant — you can decode any segment with our Base64 decoder by ticking “URL-safe”):
- Header — a small JSON object naming the signing algorithm and token type:
{"alg": "HS256", "typ": "JWT"}. - Payload — a JSON object of claims: statements about the subject and the token itself.
- Signature — a cryptographic signature over the first two segments (including the dot between them), made with a secret or private key only the issuer holds.
Crucially, the first two segments are only encoded, not encrypted. Anyone who holds a JWT can read its payload. A token is tamper-evident, not confidential.
The claims
Some payload keys are registered by the standard and mean the same thing everywhere:
iss— the issuer (“who minted this”).sub— the subject (usually the user ID).aud— the audience (which service the token is for).exp— expiry time, as a Unix timestamp in seconds. Paste it into the timestamp converter to see the exact moment a token dies.nbf— not valid before this time.iat— issued-at time.jti— a unique token ID, used for revocation lists.
Everything else is a custom claim chosen by the issuer — roles, names, tenant IDs. Two rules govern claims in practice: keep them few (the token travels with every request), and never put secrets or personal data you would not print on a postcard (see above: anyone can read them).
How verification works
A receiving service recomputes the signature over the received header and payload using the issuer’s key (a shared secret for HS256, a public key for RS256/ES256), and compares it with the third segment. If any byte of the first two segments changed, the signature does not match and the token is rejected. The service then checks exp, nbf, iss and aud.
This design is what makes JWTs stateless: the claims and their proof travel together, so verification needs no database lookup and no call to the issuer. The price of statelessness is revocation: a signed token is valid until exp no matter what happens — logout, password change, account ban. Real systems mitigate with short expiry plus refresh tokens, or a denylist of jti values, each of which reintroduces a little state.
The mistakes that make JWTs insecure
- Trusting the payload without verifying the signature. Decoding is not verifying. Any client can mint a token claiming to be an admin; only the signature distinguishes it.
- Accepting
alg: none, or letting the token choose the algorithm. Attackers have exploited verifiers that obeyed the header — including the classic confusion where an RS256 public key was used as an HMAC secret. Pin the expected algorithm in the verifier. - Putting sensitive data in claims. Payloads get logged, stored in browsers and pasted into debugging tools. Treat them as public.
- Long expiry for access tokens. A stolen stateless token is a stolen session until
exp. Minutes to an hour is the usual range; refresh tokens carry the long lifetime instead. - Skipping
aud/isschecks. A token minted for one service (or a different environment) should not open another — but it will, if the verifier never checks.
When to use a JWT — and when not to
JWTs shine for API authentication across services, especially where many independent services must verify credentials issued by one authority, and for short-lived, purpose-scoped tokens (download links, email verification). They are a poor fit when you need instant revocation, when sessions are long and server-rendered anyway (a classic opaque session cookie is simpler and revocable), or when the “claims” keep growing — a 4 KB token on every request is a smell. Understanding a token starts with looking inside it: decode the segments, read the claims, check the expiry. Just remember that reading is only step one; trust begins at the signature.