JSON Web Tokens (JWTs) are everywhere in modern web development — they power login sessions, API authentication and single sign-on. But the first time you see one, it looks like a meaningless wall of characters. This guide breaks a JWT into its three parts, shows you how to read what is inside one, and explains how to tell a valid token from a forged one.
What a JWT actually is
A JWT is just a string with three parts separated by dots: header.payload.signature. Each part is Base64url-encoded (a URL-safe variant of Base64), which is why it looks scrambled but is not actually encrypted. That is the single most important thing to understand: a JWT is encoded, not encrypted. Anyone can read the contents. The signature is what stops them changing it.
Part 1: the header
Decode the first segment and you get a small JSON object describing how the token was signed:
{ "alg": "HS256", "typ": "JWT" }
alg is the signing algorithm (more on that below) and typ is the token type. That is usually all you will find here.
Part 2: the payload (the claims)
The middle segment is the interesting one. It holds the “claims” — statements about the user and the token itself. Some claim names are standardised:
iss— issuer: who created the tokensub— subject: usually the user ID the token representsaud— audience: who the token is intended forexp— expiry: a Unix timestamp after which the token is invalidiat— issued at: when the token was creatednbf— not before: the token is invalid until this timejti— a unique ID for the token
Those exp, iat and nbf values are Unix timestamps, so a quick way to sanity-check a token is to run them through a timestamp converter. Alongside the standard claims you will usually find custom ones — a username, a role, a list of permissions — whatever the application chose to include.
Part 3: the signature
The third segment is the security. The server takes the encoded header and payload and signs them. With an HMAC algorithm like HS256 it uses a single secret key that both signs and verifies. With an RSA or ECDSA algorithm like RS256 it signs with a private key and anyone can verify with the matching public key — which is how single sign-on providers let many services trust the same token.
If someone changes a single character of the payload — say, flipping "role": "user" to "role": "admin" — the signature no longer matches, and any server that checks it will reject the token.
Reading a token safely
Because the payload is readable, never put anything secret in it — no passwords, no API keys, no personal data you would not want exposed. Treat it as public information signed for integrity, not privacy. A few more rules worth knowing:
- Always verify the signature before trusting any claim. Decoding is not verifying.
- Reject
alg: none. Some older libraries accepted unsigned tokens — a classic vulnerability. - Check
exp. An expired token should never be accepted, however valid the signature. - Keep your signing secret long and random. A weak HMAC secret can be brute-forced offline.
Try it yourself
The fastest way to understand a JWT is to pull one apart. Our free ateByteApps DevTools includes a JWT decoder that splits any token into its header, payload and signature and shows the decoded claims instantly — and because it runs entirely in your browser, the token never leaves your machine. Paste one in and the structure above will click into place.
3 comments for “What’s inside a JWT? Decoding and verifying JSON Web Tokens”