Understanding JWT Tokens: Structure, Usage and Security
JSON Web Tokens (JWTs) have become the standard way to handle authentication in modern web applications. They appear in authorization headers, OAuth flows, and single sign-on systems. If you work with APIs, understanding how JWTs work is essential for building secure applications.
What is a JWT?
A JWT is a compact, URL-safe token that carries a set of claims (pieces of information) as a JSON object. It is digitally signed, which means the recipient can verify that the contents have not been tampered with. JWTs are defined in RFC 7519 and are widely supported across programming languages and frameworks.
The Three-Part Structure
Every JWT consists of three parts separated by dots: header.payload.signature. Each part is Base64URL-encoded.
Header
The header is a JSON object that describes the token type and the signing algorithm. A typical header looks like {"alg": "HS256", "typ": "JWT"}. The alg field specifies the algorithm used to create the signature, such as HMAC-SHA256 (HS256) or RSA-SHA256 (RS256).
Payload
The payload contains the claims. These are statements about the user and additional metadata. The JWT specification defines several registered claims:
iss(issuer): who created the token.sub(subject): the user or entity the token represents.exp(expiration): a Unix timestamp after which the token is invalid.iat(issued at): when the token was created.aud(audience): who the token is intended for.
You can also include custom claims like role, email, or permissions. Keep the payload small, since the token is sent with every request.
Signature
The signature is created by taking the encoded header and payload, concatenating them with a dot, and signing the result using the algorithm specified in the header. For HS256, this means computing an HMAC using a shared secret. For RS256, it means signing with an RSA private key. The signature ensures that the token has not been modified. The server can verify it using the same secret (symmetric) or the corresponding public key (asymmetric).
How JWT Authentication Works
The typical flow is straightforward. The user logs in with their credentials. The server validates them, creates a JWT containing the user's identity and permissions, and sends it back. The client stores this token (usually in memory or an httpOnly cookie) and includes it in the Authorization header of subsequent requests as Bearer <token>. The server verifies the signature and reads the claims without needing a database lookup.
Security Best Practices
- Always verify the signature. Never trust a JWT without validating it on the server side.
- Set short expiration times. Tokens should expire in minutes or hours, not days. Use refresh tokens for longer sessions.
- Never store sensitive data in the payload. The payload is only encoded, not encrypted. Anyone with the token can read it.
- Use strong secrets. For HS256, use at least 256 bits of randomness. Better yet, use asymmetric algorithms like RS256 or ES256.
- Validate all claims. Check
exp,iss, andaudon every request, not just the signature. - Reject the "none" algorithm. Some libraries accept
alg: "none"by default, which skips signature verification entirely. Always enforce a specific algorithm.
When Not to Use JWT
JWTs are not the right solution for every scenario. If you need to revoke individual sessions immediately (such as when a user changes their password), server-side sessions with a session store are simpler and more reliable. JWTs cannot be truly revoked before they expire without maintaining a blocklist, which defeats much of their stateless advantage. Also avoid using JWTs for storing large amounts of data, since they add overhead to every HTTP request.
Try it yourself
Paste a JWT to decode and inspect its header, payload, and signature. All processing happens in your browser.
Open JWT Debugger