How to Decode a JWT Token: Structure and Security
What is a JWT Token?
A JSON Web Token (JWT, pronounced âjotâ) is an open standard (RFC 7519) for securely transmitting information between parties as a JSON object. JWTs are widely used in modern web applications for authentication and authorization. They are compact, URL-safe, and self-containedâmeaning all the necessary information is stored within the token itself.
A JWT looks like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Notice the two periods (.) that separate the token into three distinct parts.
The Three Parts of a JWT
1. Header
The header typically consists of two fields: the token type and the signing algorithm.
{
"alg": "HS256",
"typ": "JWT"
}
This JSON is Base64URL-encoded to form the first part of the token. Common algorithms include:
- HS256: HMAC using SHA-256 (symmetric)
- RS256: RSA Signature with SHA-256 (asymmetric)
- ES256: ECDSA using P-256 curve and SHA-256
2. Payload
The payload contains the claimsâstatements about the entity (usually the user) and additional data.
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
Registered claims include:
| Claim | Name | Description |
|---|---|---|
iss | Issuer | Who issued the token |
sub | Subject | Who the token refers to |
aud | Audience | Intended recipient |
exp | Expiration | When the token expires |
nbf | Not Before | When the token becomes valid |
iat | Issued At | When the token was issued |
jti | JWT ID | Unique identifier for the token |
You can add any custom claims you need, but avoid putting sensitive data in the payloadâitâs not encrypted.
3. Signature
The signature is used to verify that the token hasnât been tampered with. For HS256:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
The signature ensures integrity but does not provide confidentiality. The header and payload are merely encoded, not encrypted.
Decoding a JWT
Decoding a JWT is straightforward since the header and payload are just Base64URL-encoded JSON:
function decodeJWT(token) {
const parts = token.split('.');
if (parts.length !== 3) {
throw new Error('Invalid JWT format');
}
const header = JSON.parse(atob(parts[0].replace(/-/g, '+').replace(/_/g, '/')));
const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
return { header, payload };
}
// Usage
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
const decoded = decodeJWT(token);
console.log(decoded.header); // { alg: "HS256", typ: "JWT" }
console.log(decoded.payload); // { sub: "1234567890", name: "John Doe", iat: 1516239022 }
For a quicker way, use the JWT Decoder tool on CodeKit to instantly decode and inspect any JWT token right in your browser.
Security Best Practices
Never Store Sensitive Data in the Payload
Since the payload is only Base64URL-encoded, anyone who intercepts the token can read its contents. Never store passwords, social security numbers, or other sensitive information in JWT claims.
Always Validate the Signature
Decoding a JWT without verifying its signature is dangerous. An attacker could modify the payload and re-encode it. Always verify the signature using the appropriate secret or public key:
// Using a library like jsonwebtoken in Node.js
const jwt = require('jsonwebtoken');
const decoded = jwt.verify(token, 'your-secret-key');
// Throws an error if the signature is invalid
Set Reasonable Expiration Times
Always include an exp claim and keep expiration times short. Access tokens should typically expire in 15â30 minutes. Use refresh tokens with longer lifetimes to obtain new access tokens.
Use HTTPS
Always transmit JWTs over HTTPS. Tokens sent over plain HTTP can be intercepted by anyone on the network.
Store Tokens Securely
- Browser: Store tokens in memory or httpOnly cookies, not in localStorage (vulnerable to XSS)
- Mobile: Use the platformâs secure storage (Keychain on iOS, EncryptedSharedPreferences on Android)
Consider the Algorithm
- HS256 is simpler but requires sharing the secret with all parties
- RS256 is preferred for distributed systemsâthe signing key is private, but the verification key is public
Common Pitfalls
- âNoneâ algorithm attack: Some JWT libraries accept
{"alg": "none"}which bypasses signature verification. Always validate the algorithm explicitly. - Token leakage via URLs: Avoid putting tokens in URL parametersâthey can be logged by proxies and servers. Use the Authorization header instead.
- Not revoking tokens: JWTs are stateless by design, making revocation tricky. Consider maintaining a token blacklist or using short expiration times.
Conclusion
JWTs are a powerful tool for authentication and authorization in modern web applications. Understanding their three-part structure helps you debug issues and implement them securely. Remember: decode for inspection, verify for trust.
Want to quickly inspect a JWT token? Try the JWT Decoder on CodeKitâpaste your token and instantly see the decoded header and payload.