LW IT Solutions
« Blog Overview /Web Development / JSON Web Tokens: Structure, What Belongs in...
Read this article in other languages:

JSON Web Tokens: Structure, What Belongs in the Payload and the Difference Between Decoding and Verifying

JSON Web Tokens: Structure, What Belongs in the Payload and the Difference Between Decoding and Verifying
Contents
  1. The Three Parts and What Each Does
  2. What Has No Business in the Payload
  3. exp Is the Only Thing That Ends a Token
  4. Where Decoding Gets Confused With Verifying
  5. What Belongs in Every Token
  6. Questions and answers
  7. Sources

A JSON Web Token looks encrypted. It is a long run of characters with no readable words in it, it appears in an Authorization header, and it is handled like a secret. What it actually is: two JSON objects in base64, plus a signature – and base64 is an encoding, not a lock.

The consequence is short. Everything in the payload is readable by anyone who has the token: the browser it was sent to, the proxy it passed through, the log file that recorded the URL, and the support ticket someone pasted it into. That is not a defect; it is how the format works. It only becomes a problem when the payload is written as though nobody were reading.

A token split into its three dot-separated parts with header and payload decoded into readable JSON, marked as readable by anyone, and the signature marked as the only part that protects anything
Two of the three parts are readable by anyone. The third is the only one that protects anything.

The Three Parts and What Each Does

A token is three sections separated by dots. The first names the algorithm and, often, the key that was used. The second carries the claims – who the token is about, what it may do, how long it is valid. The third is the signature over the first two.

Only the third part does any protecting, and it protects exactly one property: that the first two have not been changed since they were signed. It does not hide them, and it does not need to be understood in order for them to be read. A token pasted into any decoder gives up its contents immediately.

What Has No Business in the Payload

Every field in the payload is a field handed to whoever holds the token. An email address, a full name, a date of birth – these turn a credential into a data disclosure, and they end up in places that credentials reach and personal data should not: proxy logs, browser storage, error reports.

The second category is internal structure. A list of roles like billing_admin or a tenant id says what exists behind the API and how it is organised, which is exactly what an attacker enumerates first. A short subject and a scope are usually enough; the rest belongs in the lookup the server does anyway.

The third is anything that was only ever meant for the issuer. Tokens are copied into support tickets, and a payload that carries an internal customer number leaves with them.

exp Is the Only Thing That Ends a Token

A token is valid because it says it is. There is no server-side state that ends it: once issued, it works until the exp claim has passed, and a token without exp works forever.

That is why logging out does not invalidate anything. The client discards the token, the token remains valid, and anyone who kept a copy keeps the access. Ending a token before its time takes a deny list that every service checks – which reintroduces exactly the shared state the format was meant to avoid.

The workable arrangement is a short-lived access token and a refresh token that can be revoked centrally. Minutes for the first, and a lifetime for the second that someone actually monitors: a refresh token with a year’s validity is a password with extra steps.

Where Decoding Gets Confused With Verifying

Reading a token and trusting it are different operations, and the difference is a library call. A decoder shows the claims of any token, including one that was written by hand three seconds ago. Verification checks the signature against a key, and only that answers whether the claims were issued by anyone entitled to issue them.

Two failure modes follow from confusing them. The first is alg: none – a token that declares it has no signature. A verifier that reads the algorithm out of the token and obliges will accept anything; the algorithm has to be fixed by the application, not by the token. The second is the same mistake with a key: a service expecting RS256 that is handed an HS256 token can be talked into verifying it with the public key as the shared secret – and the public key is public.

What Belongs in Every Token

Three claims are worth insisting on. exp, because without it nothing ends. iss, so a service can tell which issuer a token came from rather than accepting anything that verifies. And aud, which is the one that stops a token minted for the reporting API from being accepted by the billing API – a check that is easy to skip and hard to notice missing.

None of this needs tooling to review. Splitting a token at its dots and decoding the middle part takes seconds, and it answers the questions that otherwise get answered by assumption: how long this is valid, what it permits, and what it tells anyone who reads it.

Questions and answers

What happens to tokens already issued when the signing key is rotated?

They stay valid for as long as the verifier still knows the old key. The signature is checked against a key from the verifier’s own list, usually the one named in the first part of the token. Once that key disappears from the list, every token signed with it fails at once, whatever its exp says.

For a planned rotation this dictates an order. The verifiers learn the new key first, then the issuer starts signing with it, and the old key stays in place until the last token it signed has expired. With access tokens that live for minutes, the overlap is short; if refresh tokens are issued as signed tokens too, it stretches as far as their lifetime.

Conversely, removing a key ends every token signed with it ahead of time, with no deny list at all. That is the right move when the signing key has fallen into the wrong hands, but it hits every client at once. In any case, the key reference in the token may only select among keys the verifier holds itself, for the same reason the algorithm must not come from the token.

Can the payload be encrypted instead of being kept short?

Yes, with JSON Web Encryption as defined in RFC 7516, and then only a holder of the key can read the contents. The token remains a credential all the same: a copy in a support ticket or a log file becomes unreadable but stays just as usable until exp has passed. A field the server can look up anyway therefore needs no encryption; it needs no place in the token at all.

What does it mean for exp when the clocks of the servers involved drift apart?

exp is a point in time, and it is compared against the clock of the verifying service, not the issuer’s. If that clock runs behind, the service still accepts a token that has already expired. If it runs ahead, the lifetime shrinks by the offset, and for an access token that lives a few minutes, a single minute is already a noticeable share of it. For nbf, the time from which a token is valid, the offset works the other way round: a service whose clock runs behind rejects a freshly issued token as not yet valid.

RFC 7519 allows a small leeway for this, usually no more than a few minutes, and most libraries offer a setting for it. The leeway does, however, extend every token by exactly that amount, and two minutes of leeway on an access token with a five-minute lifetime is no minor matter. The more reliable approach is to keep every machine involved synchronised via NTP and to leave the leeway at a few seconds.

Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Get in Touch

Briefly describe your project or inquiry for a tailored response. This site is protected by reCAPTCHA.

Write a comment

Edge cases the article misses and questions about the code are welcome here.

The email address is not published. Required fields are marked with an asterisk.

Articles & categories

CCTV

Follow this category by RSS

Cloud & AI

All 17 articles in this category Follow this category by RSS

Data Privacy

All 19 articles in this category Follow this category by RSS

Digital Analytics

All 58 articles in this category Follow this category by RSS

Digital Marketing

All 37 articles in this category Follow this category by RSS

IT & Networks

All 19 articles in this category Follow this category by RSS

Music Production

All 17 articles in this category Follow this category by RSS

Raspberry PI

Follow this category by RSS

SaaS & Internet Earning

Follow this category by RSS

Smart Home

All 18 articles in this category Follow this category by RSS

Web Development

All 11 articles in this category Follow this category by RSS

WordPress Plugins & Tricks

All 14 articles in this category Follow this category by RSS