How JWTs Work: Header, Payload and Signature
Understand how JSON Web Tokens work and how to inspect them safely.
JWT (JSON Web Token) is the standard way to transmit information securely between systems. If you've ever seen a token that looks like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
...that's a JWT. Let's decode it.
JWT Structure
A JWT is three Base64-encoded parts separated by dots:
header.payload.signature
Part 1: Header
The header is Base64-decoded metadata about the token.
{
"alg": "HS256",
"typ": "JWT"
}
- alg: The algorithm used to sign the token (HS256, RS256, etc.)
- typ: Always "JWT"
Part 2: Payload
The payload contains the actual data (claims). This is what the application uses.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
Common claims:
- sub: Subject (usually a user ID)
- iss: Issuer (who created the token)
- aud: Audience (who should accept it)
- iat: Issued at (Unix timestamp)
- exp: Expiration time (Unix timestamp)
- name, email, roles: Custom data
Part 3: Signature
The signature proves the token hasn't been tampered with.
The server that created the token uses a secret key plus the header and payload to create the signature:
signature = HMAC-SHA256(
base64(header) + "." + base64(payload),
secret_key
)
If someone modifies the payload, the signature no longer matches. That's how the server detects tampering.
How JWT Authentication Works
1. User logs in with username/password
2. Server verifies credentials, creates a JWT
3. Server returns the JWT to the client
4. Client stores the JWT (usually in localStorage)
5. On each request, client sends: Authorization: Bearer {token}
6. Server verifies the signature (using the same secret key)
7. If signature is valid, server trusts the payload claims
Important: Decoding is NOT Verifying
You can decode any JWT to see its payload. Use the DevToolkit JWT Decoder.
But decoding doesn't mean verifying. To verify, you need:
1. The original secret key (only the server has this)
2. Check that the signature matches
Anyone can decode a JWT. Only someone with the secret key can verify it's legitimate.
Example
Encoded JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5ODc2NTQzMjEiLCJuYW1lIjoiQWxpY2UiLCJhZG1pbiI6dHJ1ZSwiaWF0IjoxNjA0MDI3MDAwfQ.d8m5w9x2c4_tJ6kL9_pZ
Decoded header:
{
"alg": "HS256",
"typ": "JWT"
}
Decoded payload:
{
"sub": "9876543210",
"name": "Alice",
"admin": true,
"iat": 1604027000
}
The signature is verified by only the server (using the secret key).
Security Best Practices
- Never put sensitive data (passwords, credit cards) in JWT payload. It's encoded, not encrypted.
- Always use HTTPS. A JWT can be intercepted over HTTP.
- Set short expiration times (minutes, not days)
- Use HS256 or RS256 algorithms (not none)
- Store the secret key securely on the server
- Rotate keys periodically
- Validate expiration (exp) on every request
Algorithm Notes
- HS256 (HMAC-SHA256): Server signs with secret key. Good for internal services.
- RS256 (RSA-SHA256): Server signs with private key, client verifies with public key. Good for public APIs.
- none: No signature. Never use this in production.
When to Use JWT
- API authentication (most common)
- OAuth/OpenID Connect flows
- Sharing identity between services
- Mobile apps (better than cookies)
- Microservices communication
When NOT to Use JWT
- Don't rely on claims without verifying the signature
- Don't store JWTs longer than necessary
- Don't put sensitive data in the payload
Tools
DevToolkit's JWT Decoder lets you inspect any token instantly. Remember: decoding shows the payload, but only the server can verify it's legitimate.