JSON Web Tokens (JWT), Explained

JSON Web Tokens are everywhere in modern authentication — and widely misunderstood. The biggest myth is that a JWT is encrypted and therefore safe to put secrets in. It isn't. This guide breaks down exactly what a JWT contains, what every claim means, how signing works, and where the real security boundary lies.

What is a JWT?

A JWT (JSON Web Token, RFC 7519) is a compact, URL-safe way to represent claims — statements about a subject — that are transferred between two parties. In practice you'll meet them most often as access tokens: after you log in, a server hands your client a JWT, and the client sends it back on every request to prove who it is.

"Compact" and "URL-safe" matter: a JWT is short enough to fit in an HTTP Authorization header and contains only characters that are safe in URLs and cookies.

JWTs are popular because they're stateless. A traditional session stores data on the server and gives the client an opaque id; the server must look that id up on every request. A JWT instead carries the claims inside the token, signed so the server can trust them without a database lookup.

The three parts of a JWT

A JWT is three Base64url-encoded segments joined by dots:

header.payload.signature

For example:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiQWRhIn0.4pcPyMD0...

Each segment decodes to something human-readable. (Note: this is Base64url, a URL-safe variant — +// become -/_ and padding = is dropped.)

1. Header

The header is a small JSON object describing how the token is signed:

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

2. Payload (the claims)

The payload carries the claims. Several are registered as standard:

Claim Name Meaning
iss Issuer Who created and signed the token
sub Subject Who the token is about (often a user id)
aud Audience Who the token is intended for
exp Expiration Unix time after which the token is invalid
iat Issued At Unix time the token was created
nbf Not Before Unix time before which the token is invalid
jti JWT ID A unique id, useful for revocation lists

You can also add your own custom (private) claims — roles, tenant id, plan — but keep the token small, because it's sent on every request.

3. Signature

The signature is computed over the encoded header and payload using either a shared secret (HMAC, e.g. HS256) or a private key (RSA/ECDSA, e.g. RS256/ES256). It lets a recipient verify two things: that the token hasn't been tampered with, and that it was issued by someone holding the key.

Signing algorithms

Family Examples Key model
HMAC HS256, HS384, HS512 One shared secret signs and verifies
RSA RS256, RS384, RS512 Private key signs, public key verifies
ECDSA ES256, ES384 Like RSA but smaller keys/signatures

Use HMAC when the same trusted service both issues and verifies tokens. Use RSA/ECDSA when many parties need to verify tokens but only one should be able to issue them (e.g. an identity provider publishing a public key).

Decoding vs. verifying — the key distinction

This is the part that trips people up:

A JWT is signed, not encrypted. Decode it freely for debugging, but never store passwords, API keys, or other secrets in the payload — anyone with the token can read them. If you genuinely need a confidential payload, use JWE (JSON Web Encryption).

Common pitfalls

JWT vs. session cookies

JWT (stateless) Session (stateful)
Where state lives In the token On the server
Revocation Hard (until exp) Easy (delete the session)
Scaling No shared session store needed Needs shared/sticky store
Size on the wire Larger Small opaque id

Neither is universally "better" — JWTs shine for distributed services and APIs; server sessions shine when instant revocation matters.

Decode a JWT online

The JWT Decoder splits a token into its header and payload and shows the exp/iat times in a readable form — without verifying the signature, and without sending the token anywhere. It runs entirely in your browser, so the token never leaves your device.

Frequently asked questions

Is a JWT encrypted? No. It's signed and Base64url-encoded. Anyone can read the payload; the signature only guarantees integrity.

Can I trust a JWT I just decoded? Not on its own. Decoding proves nothing — you must verify the signature and check exp/aud/iss with the issuer's key.

Where should I store a JWT in a browser? Prefer an HttpOnly, Secure cookie to reduce XSS exposure; avoid localStorage for sensitive tokens.

What's the difference between a JWT and an opaque token? A JWT is self-describing and verifiable without a lookup; an opaque token is a random id that only means something to the server that issued it.

Is my token uploaded when I decode it here? No. The JWT Decoder runs entirely in your browser.

Keep going

Decodificador de JWT