What is a JWT? JSON Web Tokens explained
By Uxair Ijaz · 2026-10-22 · 3 min read
A JSON Web Token (JWT, pronounced "jot") is a compact, URL-safe string that carries a small JSON object from one system to another, together with a signature that proves it has not been changed. You will meet them in login flows, API authorisation headers and single sign-on.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiQWRhIiwiZXhwIjoxOTAwMDAwMDAwfQ.s5Jq8pW0v0bq1aFz9k0y2bYQ7sXQyUQd1c2cG0pVb0E
The three parts
A JWT is three Base64URL-encoded pieces joined by dots: header.payload.signature.
- Header: which algorithm signed the token, for example
{"alg": "HS256", "typ": "JWT"}. - Payload: the claims, the data the token is about.
- Signature: a cryptographic signature over the first two parts.
The header and payload are only encoded, not encrypted. Anyone who has the token can read them; paste one into the JWT decoder and you will see the JSON straight away. Never put secrets in a JWT payload.
Common claims
| Claim | Meaning |
|---|---|
sub |
Subject: who the token is about (usually a user id) |
iss |
Issuer: who created the token |
aud |
Audience: who the token is meant for |
exp |
Expiry time, as a Unix timestamp in seconds |
iat |
Issued at, also in seconds |
nbf |
Not valid before this time |
Times are seconds since 1970, not milliseconds. The timestamp converter turns them into readable dates.
How the signature works
The server takes base64url(header) + "." + base64url(payload) and signs it:
- HS256 (HMAC with SHA-256) uses one shared secret to sign and to verify. It is simple, but every service that verifies tokens must hold the secret.
- RS256 / ES256 use a key pair. The issuer signs with a private key and anyone can verify with the public key, which is why identity providers publish their keys at a JWKS URL.
When a request arrives, the server recomputes the signature. If a single character of the payload has changed, the signatures no longer match and the token is rejected.
Mistakes to avoid
- Trusting the payload without verifying the signature. Decoding is not verifying.
- Accepting
alg: noneor letting the token choose its own algorithm. Pin the algorithm on the server. - Long-lived tokens. A JWT cannot easily be revoked before it expires; keep
expshort and use refresh tokens. - Storing tokens where scripts can read them if your site is exposed to XSS. HttpOnly cookies are often safer than
localStorage. - Weak HMAC secrets. Use at least 32 random bytes; the password generator can make one.
JWT or PASETO?
PASETO is a newer token format with the same idea but fewer choices: each version fixes the algorithms, so the "pick a weak algorithm" class of mistakes disappears. If you control both ends, it is worth a look: the complete PASETO guide covers it in depth.
Try it
Open the JWT encoder / decoder, paste a token to read its claims and check when it expires, or build and sign a test token with your own secret. Everything runs in your browser, so the token never leaves your machine.