JSON Web Tokens (JWT) are everywhere in modern web development. They power authentication, authorization, and secure data transfer. But when something goes wrong with your JWT, how do you inspect what's inside? This guide covers everything you need to know about decoding JWT tokens safely.
Decode JWT Tokens Free
Our JWT decoder runs 100% in your browser. Your tokens never leave your device.
Try JWT Decoder⚠️ Security Warning
Never paste production JWT tokens containing sensitive data into online decoders you don't trust. Many web-based JWT decoders send your token to their servers for processing. Always verify the tool runs client-side.
What is a JWT Token?
A JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. It consists of three parts:
Header (Part 1)
The header contains metadata about the token, including the signing algorithm:
{
"alg": "HS256",
"typ": "JWT"
}
Payload (Part 2)
The payload contains the claims — the actual data you want to transmit:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}
Signature (Part 3)
The signature verifies the token's authenticity. It's created by combining the encoded header, encoded payload, and a secret key:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
How to Decode a JWT Token
Decoding a JWT is straightforward because the header and payload are simply Base64Url encoded. Here's how to do it manually:
Method 1: Using Browser Console
// Decode JWT header and payload
function decodeJWT(token) {
const [header, payload, signature] = token.split('.');
const decodedHeader = JSON.parse(atob(header.replace(/-/g, '+').replace(/_/g, '/')));
const decodedPayload = JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/')));
return {
header: decodedHeader,
payload: decodedPayload,
signature: signature
};
}
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
console.log(decodeJWT(token));
Method 2: Using Online Tools
Online JWT decoders provide a visual interface for inspecting tokens. They're convenient but come with security considerations:
- ✅ Pros: Visual interface, instant validation, signature verification options
- ❌ Cons: May send tokens to servers, potential data exposure
🚨 Critical Security Reminder
DevKits JWT Decoder runs 100% client-side. Your tokens never leave your browser. This is crucial for production debugging where tokens may contain sensitive user data.
Common JWT Claims
Understanding JWT claims is essential for debugging authentication issues:
| Claim | Name | Description |
|---|---|---|
iss |
Issuer | Who issued the token |
sub |
Subject | The subject (usually user ID) |
aud |
Audience | Who the token is for |
exp |
Expiration | When token expires (Unix timestamp) |
nbf |
Not Before | Token is not valid before this time |
iat |
Issued At | When token was created |
jti |
JWT ID | Unique identifier for the token |
Verifying JWT Signatures
Decoding shows you the claims, but verification proves the token hasn't been tampered with:
Why Verification Matters
Anyone can create a JWT with any payload. Without signature verification, you're trusting that the sender is who they claim to be.
🚨 The "alg: none" Vulnerability
Some JWT libraries accept tokens with "alg": "none", which means no signature verification. Attackers can forge tokens by changing the algorithm to "none" and removing the signature. Always verify the algorithm matches your expectations.
Manual Verification (Node.js)
const crypto = require('crypto');
function verifyJWT(token, secret) {
const [headerB64, payloadB64, signature] = token.split('.');
// Decode header to get algorithm
const header = JSON.parse(atob(headerB64.replace(/-/g, '+').replace(/_/g, '/')));
if (header.alg !== 'HS256') {
throw new Error('Unsupported algorithm');
}
// Calculate expected signature
const data = `${headerB64}.${payloadB64}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(data)
.digest('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
return signature === expectedSignature;
}
Common JWT Debugging Scenarios
1. Token Expired
Symptom: API returns "Token expired" error
Debug: Decode the token and check the exp claim:
const payload = decodeJWT(token).payload;
const expiresAt = new Date(payload.exp * 1000);
console.log('Token expired:', new Date() > expiresAt);
Fix: Implement token refresh or re-authentication
2. Invalid Signature
Symptom: Server rejects token with "Invalid signature"
Debug: Check if:
- Secret key matches between issuer and verifier
- Algorithm is consistent (HS256 vs RS256)
- Token wasn't modified in transit
3. Missing Claims
Symptom: Authorization fails despite valid token
Debug: Decode and verify required claims are present:
const requiredClaims = ['sub', 'exp', 'iat'];
const payload = decodeJWT(token).payload;
const missing = requiredClaims.filter(claim => !(claim in payload));
if (missing.length > 0) {
console.error('Missing claims:', missing);
}
4. Wrong Audience
Symptom: Token rejected by resource server
Debug: Check aud claim matches expected audience:
const payload = decodeJWT(token).payload;
if (payload.aud !== 'api.myapp.com') {
console.error('Wrong audience:', payload.aud);
}
Security Best Practices
For Token Generation
- Use strong, randomly generated secrets (at least 256 bits)
- Set reasonable expiration times (15 minutes to 24 hours)
- Include only necessary claims — avoid sensitive data
- Use RS256 (asymmetric) for distributed systems
For Token Validation
- Always verify the signature before trusting claims
- Check expiration (
exp) and not-before (nbf) times - Validate the issuer (
iss) and audience (aud) - Reject tokens with unexpected algorithms
For Debugging
- Use client-side decoders (like DevKits) for production tokens
- Never log full JWT tokens in application logs
- Mask tokens in debug output, showing only the subject
- Use separate test tokens for development
Decode JWT Tokens Safely
DevKits JWT Decoder runs 100% in your browser. No server calls, no data storage.
Decode JWT NowJWT Algorithms Compared
| Algorithm | Type | Use Case | Security |
|---|---|---|---|
| HS256 | Symmetric | Single service | Good (shared secret) |
| HS384/HS512 | Symmetric | Single service | Better (longer keys) |
| RS256 | Asymmetric | Distributed systems | Excellent (public/private key) |
| RS384/RS512 | Asymmetric | Distributed systems | Excellent (longer keys) |
| ES256 | ECDSA | Mobile/IoT | Excellent (smaller signatures) |
JWT Development Tools
Beyond decoding, here are essential JWT tools every developer should have:
- JWT Decoder — Inspect token contents
- JWT Generator — Create test tokens
- JWT Validator — Verify signatures programmatically
- Token Blacklist — Implement token revocation
- Refresh Token Handler — Manage token lifecycle
Conclusion
JWT tokens are fundamental to modern authentication, but debugging them requires understanding their structure, claims, and security implications. Whether you're troubleshooting an expired token, verifying a signature, or just learning how JWTs work, having the right tools makes all the difference.
Remember: always use client-side decoders for production tokens, verify signatures before trusting claims, and never expose sensitive data in JWT payloads.
Try DevKits JWT Decoder
100% client-side JWT decoding. Your tokens never leave your browser.
Decode JWT FreeRelated Reading: