A JWT (JSON Web Token) is a compact, self-contained way to carry claims — like who a user is — between two parties, signed so it can't be tampered with. Here's how it's built and what each part does, with a free decoder to look inside any token.
Decode a JWT free →The three parts
A JWT is three Base64URL parts separated by dots: a header (the signing algorithm and token type), a payload (the claims, like sub, iat and exp), and a signature (which proves the token wasn't changed). Only the signature needs the secret — the header and payload are just encoded.
Encoded, not encrypted
This is the part people miss: a JWT's payload is readable by anyone who has the token — it's Base64, not encryption. Never put passwords, secrets or sensitive personal data in a JWT payload.
Common claims
Standard fields you'll see in the payload:
- sub — the subject (usually the user)
- iat — issued-at time
- exp — expiry time
- nbf — not valid before
- iss — the issuer
- aud — the intended audience
iat, exp and nbf are Unix timestamps you can convert to a readable date.
How signing works
The server signs the header and payload with a secret (HMAC) or a private key (RSA/EC). Anyone with the matching secret or public key can verify the signature — that's how a server trusts a token it receives without storing anything.
When to use a JWT
Stateless authentication and authorization: after login the server issues a signed JWT, the client sends it with each request, and the server verifies it without a database lookup. Keep them short-lived and pair them with refresh tokens.
Frequently asked questions
Is a JWT secure?+
The signature makes it tamper-evident, but the payload is readable by anyone holding the token. Use HTTPS, keep tokens short-lived, and never store secrets inside them.
Can I trust a decoded JWT?+
Decoding only reads the token — it does not verify the signature. To trust a token you must verify its signature with the secret or public key, which you should never paste into a public website.
Why is my JWT expired?+
If the exp claim is in the past, the token has expired and should be rejected. Convert exp from a Unix timestamp to see the exact time it lapsed.