Web & Dev

How JWT Works: The Anatomy of a JSON Web Token

The three parts of a JWT, why the payload is encoded not encrypted, how the signature makes it tamper-proof, and the security rules that keep token-based auth safe.

When you log into a modern web app and stay logged in across pages, there is a good chance a JSON Web Token (JWT) is doing the work. It is the standard way to carry proof of identity between a browser and a server without the server having to remember anything. Understanding its three parts — and one critical thing it does not do — is essential to using it safely.

Paste any token into the JWT Decoder to see its parts decoded, right in your browser — the token is never uploaded.

The problem JWTs solve

HTTP is stateless: the server forgets you between requests. Traditionally, the server kept a session in its own memory or database and gave the browser a session ID to send back each time — which means the server must store and look up state for every user. A JWT flips this: the server hands the client a signed token containing the identity info itself. On each request the client sends the token back, and the server verifies the signature and trusts the contents — no server-side lookup needed. That statelessness is why JWTs scale well across many servers.

The three parts

A JWT is three base64url-encoded chunks joined by dots: header.payload.signature.

eyJhbGc...(header).eyJzdWI...(payload).SflKxwR...(signature)
  • Header — a small JSON object naming the token type and the signing algorithm (e.g. {"alg":"HS256","typ":"JWT"}).
  • Payload — the claims: a JSON object of statements about the user and the token (who they are, when it expires, what they can do).
  • Signature — a cryptographic stamp over the header and payload, proving they have not been altered.

The header and payload are just JSON that has been base64url-encoded — which is why a decoder can read them instantly.

Claims: what is in the payload

The payload holds claims. Several are standardised:

ClaimMeaning
subSubject — who the token is about (e.g. a user ID)
issIssuer — who created the token
expExpiration time — after which it is invalid
iatIssued-at time
audAudience — who the token is intended for

You can add your own claims too (roles, permissions). But keep the payload small and non-secret — which leads to the single most important point about JWTs.

Encoded, not encrypted

⚠️The payload is readable by anyone. Base64url is encoding, not encryption — it scrambles nothing. Anyone who intercepts a JWT can decode and read every claim in it. Never put passwords, secret keys or sensitive personal data in a JWT payload.

So if anyone can read it, what makes it trustworthy? Not secrecy — integrity. That is the job of the signature. (The difference between encoding, hashing and encryption is the subject of Hashing vs Encryption vs Encoding.)

The signature: tamper-proofing

The signature is computed by running the header and payload, plus a secret known only to the server, through a signing algorithm. The result is appended as the third part. On each request the server recomputes the signature from the received header and payload using its secret and checks it matches.

  • Change a single character of the payload (say, escalate your role to admin) and the recomputed signature no longer matches → the server rejects the token.
  • Forge a token from scratch? You cannot produce a valid signature without the secret.

This is what lets the server trust a token it did not store: the maths guarantees the contents are exactly what the server signed.

Using JWTs safely

  • Always set an expiry (exp) and keep it short — a stolen token is valid until it expires.
  • Verify the signature server-side on every request; never trust the payload without checking it.
  • Keep secrets out of the payload — it is readable.
  • Use HTTPS so tokens cannot be sniffed in transit.
  • Store carefully — each option (memory, HttpOnly cookie, localStorage) trades convenience against exposure to XSS and CSRF.

In practice

A JWT is a signed, self-contained packet of JSON claims: readable by anyone, alterable by no one without the secret. Get the “encoded, not encrypted” point right and most JWT mistakes disappear. Decode and inspect real tokens with the JWT Decoder, and see how tokens fit the broader toolkit in Developer Data Essentials.

Frequently asked questions

What is a JWT?

A JSON Web Token is a compact, signed token used to prove identity between a client and server. It carries a small JSON payload (claims about the user) plus a cryptographic signature, so the server can trust it without storing session state. It is the standard for stateless authentication in modern web apps.

Is the data in a JWT encrypted?

No — by default the payload is only base64url-encoded, which is reversible by anyone. A JWT is signed, not encrypted: the signature proves it has not been tampered with, but the contents are readable. Never put secrets like passwords in a JWT payload.

What stops someone from forging a JWT?

The signature. It is computed from the header, payload and a secret (or private key) that only the server holds. Change any part of the token and the signature no longer matches, so the server rejects it. Without the secret, an attacker cannot produce a valid signature.

Where should I store a JWT?

It is a trade-off. Storing it in memory is safest against theft but lost on refresh. Cookies (ideally HttpOnly and Secure) protect against cross-site scripting but need CSRF protection. localStorage is convenient but readable by any script on the page, so it is vulnerable to XSS. Choose based on your app's threat model.

Was this article helpful?