The Problem JWT Solves
When you log into a website, the server needs a way to remember who you are on subsequent requests. HTTP is stateless โ each request is independent with no memory of previous ones.
The old approach was server-side sessions. The server stores your session in memory or a database, gives you a session ID in a cookie, and looks it up on every request. This works, but it means session data must be shared across all servers in a cluster, and it does not work well for APIs called by mobile apps or third-party services.
JWT โ JSON Web Token โ takes a different approach. Instead of storing session data on the server, the server encodes all the relevant information into a token and sends it to the client. The client sends this token with every subsequent request. The server verifies it cryptographically and extracts the data without hitting a database.
What a JWT Actually Contains
A JWT looks like three Base64URL-encoded strings joined by dots: header.payload.signature
The header contains the token type (JWT) and the signing algorithm used (typically HS256 or RS256).
The payload contains claims โ statements about the user and metadata. Standard claims include sub (subject โ the user ID), exp (expiration timestamp), iat (issued at timestamp), and iss (issuer โ who created the token). You can also add custom claims like roles, permissions, or any user data your app needs.
The signature is what makes the token trustworthy. The header and payload are hashed together with a secret key (for HS256) or signed with a private key (for RS256). The server verifies this on every request. If anyone tampers with the payload, the signature stops matching and the token is rejected.
What the Payload Looks Like When Decoded
When you decode the payload from Base64, you get a plain JSON object like this:
{
"sub": "user_12345",
"email": "alice@example.com",
"role": "admin",
"iat": 1704067200,
"exp": 1704153600
}The exp field is a Unix timestamp. When this timestamp is in the past, the token is expired and the server will reject it. This is why JWT authentication errors often look like "token expired" โ the token was valid when issued but has a short lifespan by design.
The Security Considerations You Should Know
JWTs are not secret. The header and payload are only Base64-encoded, not encrypted. Anyone who gets your token can decode it and read everything in the payload. Do not put passwords, credit card numbers, or genuinely sensitive data in a JWT payload.
The signature protects integrity, not confidentiality. The signature means nobody can modify the token without the server detecting it. But it does not prevent anyone from reading the token.
Short expiry times matter. Because JWTs cannot be easily revoked (the server does not track them), short expiration times limit the damage if a token is stolen. Access tokens typically expire in 15 minutes to an hour. Refresh tokens last longer and are used to get new access tokens.
The "none" algorithm vulnerability. Some early JWT libraries accepted tokens with the algorithm set to "none" in the header, meaning no signature was required. Modern libraries have fixed this, but it is worth knowing โ always explicitly specify which algorithms your server accepts.
How to Inspect a JWT
If you are debugging an API and need to see what is inside a token, our JWT Decoder tool decodes any JWT instantly. Paste the token and you see the header, payload, and signature breakdown with human-readable timestamps for the exp and iat fields.
This is useful for checking whether a token is expired, confirming which user ID or role is encoded, or verifying the token format when debugging authentication issues.
Related Topics
Try it yourself
JWT Decoder
Everything in this article is available in the free tool. No account, no subscription, no install.
Open JWT Decoder โ