Zoven

What Is Actually Inside a JWT? Tokens, Signatures and Expiry Explained

Security · 7 min read · 2026-10-26

Paste a JSON Web Token into a decoder and you will see something familiar: your user id, your email, maybe a role, all in plain JSON. That surprises people the first time. A JWT is not a sealed envelope - it is a POSTCARD with a tamper-evident seal. Anyone can read it; the signature only guarantees nobody altered it. Understanding that distinction is the whole subject.

Three blocks, two dots

A JWT has three Base64url-encoded sections joined by dots. The header states the algorithm (usually HS256 or RS256). The payload carries the claims: standard ones like "sub" (subject), "iat" (issued-at time), "exp" (expiry) plus whatever custom fields the application added. The signature is the first two blocks run through the signing algorithm with a secret key (or private key). Change one character of the payload and the signature no longer matches - the server rejects it without ever trusting the contents.

Signed, not encrypted

The single most common misconception is that a JWT hides its contents. It does not: the header and payload are only encoded, and decoding them takes one command. Never put anything sensitive in a token payload - no passwords, no secrets, no data you would not show the user themselves. The token's job is authentication ("who is this?"), not confidentiality. If a payload field must stay secret, it belongs in the database, referenced by an id, not embedded in the token.

The expiry dance

Why teams moved to tokens at all

Before tokens, servers kept session state and looked it up in a database on every request. Tokens move the state INTO the request: the server verifies a signature locally, in microseconds, with no database round trip. That scales horizontally - any server holding the key can verify any token - which is why APIs, microservices and single-page apps adopted them so quickly. The tradeoff is revocation: a token stays valid until it expires unless you add a deny-list, which is exactly the complexity refresh-token designs accept.

Treat a JWT like an ID badge, not a sealed letter: everyone can read the name, nobody can quietly change it, and it expires on a schedule.

Tools mentioned in this article