If you've logged into a website and stayed logged in as you clicked around, there's a good chance a JWT (JSON Web Token, usually pronounced "jot") was quietly doing the work behind the scenes. They're everywhere in modern authentication, and understanding what's actually inside one demystifies a lot of how login sessions work.

What a JWT actually is

A JWT is a compact way to package a set of claims (statements about a user, like "this is user 42" or "this token expires at 3pm") into a string that can be safely passed around, and — this is the important part — cryptographically verified as untampered without needing to check back with a database every single time.

A JWT looks like three chunks of text separated by dots:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0IiwibmFtZSI6IkFsaWNlIn0.4Q9z3lZ...

Those three parts are, in order: the header, the payload, and the signature.

Part 1: the header

Base64URL-decode the first chunk and you get a small JSON object:

{
  "alg": "HS256",
  "typ": "JWT"
}

This just says which algorithm was used to sign the token (HS256 here, a common HMAC-based option) and that it's a JWT. Nothing secret or interesting yet.

Part 2: the payload

Decode the second chunk and you get the actual claims:

{
  "sub": "1234",
  "name": "Alice",
  "iat": 1712345678,
  "exp": 1712349278
}

A few claim names show up constantly, standardized by the JWT spec itself:

Anything else — name, role, permissions — is a custom claim, added by whoever's issuing the tokens for their application's needs.

The part everyone gets wrong at first: the payload isn't secret

This is the single most important thing to understand about JWTs: the header and payload are just Base64URL-encoded, not encrypted. Encoding is not encryption — anyone who has the token can decode the payload and read every claim inside it in about two seconds, with no key needed at all. Never put a password, a credit card number, or anything genuinely secret inside a JWT payload. It's meant to be read, just not undetectably modified.

Part 3: the signature, and why it matters

The signature is what makes a JWT actually useful for security. It's created by taking the header and payload, and running them through a signing algorithm together with a secret key that only the server knows. When the server later receives the token back, it recomputes the signature from the header and payload it received, and checks whether that matches the signature attached to the token.

If even one character of the payload was changed — say, someone tried to edit "role": "user" into "role": "admin" — the recomputed signature won't match, because the signature is mathematically tied to the exact original content. The server rejects the token. This is what lets a server trust a token's claims without needing to look anything up in a database: if the signature checks out, the claims haven't been tampered with since the server itself issued them.

Why this makes JWTs good for stateless authentication

Traditional session-based login stores session data on the server (often in a database or cache) and gives the browser just a session ID to reference it. Every request means a lookup. A JWT flips this: the client holds the actual claims, and the server just verifies the signature — no database round-trip required to check who's making the request. This is a big part of why JWTs are popular for APIs with many independent services, since any service holding the same secret key can verify a token without sharing a session store.

The trade-off: you can't easily un-issue a JWT

That stateless design cuts both ways. Since the server doesn't track which tokens it's issued, there's no simple built-in way to revoke one early — if you want to force a user to log out immediately (say, after a password change or a suspected account compromise), a valid, unexpired JWT can't just be deleted from a database like a traditional session can. Common workarounds include keeping tokens short-lived (a few minutes to an hour) paired with a separate refresh mechanism, or maintaining a server-side denylist of specific revoked tokens — which reintroduces some of the server-side state JWTs were meant to avoid.

What "decoding" a JWT does and doesn't tell you

Decoding a JWT (reading its header and payload) tells you what claims it contains. It does not tell you whether those claims are trustworthy — that requires actually verifying the signature against the correct secret or public key, which only the systems that share that key can do. A tool that just decodes a JWT for you to inspect is genuinely useful for debugging, but it is not, and cannot be, proof that the token is authentic.

A quick mental model

Think of a JWT less like a locked box and more like a signed, tamper-evident letter written on clear glass. Anyone can read what's written on it. But if anyone other than the original signer tries to alter the message, the seal visibly breaks. That's the entire security model in one sentence.

Frequently Asked Questions

No, by default a JWT's header and payload are only Base64URL-encoded, not encrypted — anyone with the token can decode and read every claim. There's a less common variant called a JWE (JSON Web Encryption) that does encrypt the payload, but a standard JWT does not.
Not without knowing the secret (or private) key used to sign it. Changing even one character of the payload changes the signature that should match it, so a server correctly verifying the signature will reject a tampered token.
JWTs are designed to be stateless — the server doesn't keep a record of every token it issues, which is exactly what makes verification fast and doesn't require a database lookup. That same design means there's no built-in way to invalidate one specific token early; common solutions are short expiration times or a server-side denylist for specific revoked tokens.
Decoding just reads the Base64URL-encoded header and payload — no key needed, and it doesn't prove anything about authenticity. Verifying checks the signature against the correct secret or public key, which is the step that actually confirms the token hasn't been tampered with.