JSON Web Token (JWT) Decoder: Inspect JWT Content and Claims
· 12 min read
Table of Contents
- Understanding JSON Web Tokens
- The Three-Part Structure of JWTs
- Why Use a JSON Web Token Decoder?
- Step-by-Step Decoding Process
- Validating the Token's Signature
- Security Considerations and Best Practices
- Common JWT Issues and Solutions
- JWT vs. Traditional Session Authentication
- Real-World Use Cases and Examples
- Debugging and Troubleshooting Tips
- Frequently Asked Questions
- Related Articles
Understanding JSON Web Tokens
JSON Web Tokens (JWTs) are compact, self-contained tokens used to securely transmit information between parties as a JSON object. They've become the de facto standard for authentication and information exchange in modern web applications, mobile apps, and microservices architectures.
Unlike traditional session-based authentication where user data is stored on the server, JWTs embed the data directly within the token itself. This fundamental difference makes JWTs ideal for stateless operations—the server doesn't need to maintain session storage or query a database to verify user identity on every request.
Think of a JWT like a digital passport. Just as a passport contains your identity information and is cryptographically secured with holograms and watermarks, a JWT contains claims about a user and is cryptographically signed to prevent tampering. When you present your passport at border control, officials can verify its authenticity without calling your home country—similarly, services can verify JWTs without contacting the issuing server.
Pro tip: JWTs are particularly useful in distributed systems and microservices architectures where maintaining centralized session state would create bottlenecks. Each service can independently verify tokens without cross-service communication.
Common scenarios where JWTs shine include:
- Single Sign-On (SSO): Users authenticate once and access multiple services with the same token
- API Authentication: Mobile apps and SPAs authenticate with backend APIs without cookies
- Information Exchange: Securely transmit verified data between services
- Stateless Authorization: Grant temporary access to resources without server-side sessions
The Three-Part Structure of JWTs
Every JWT consists of three distinct parts separated by periods (dots). Each part serves a specific purpose in the token's functionality and security model. When you see a JWT, it looks like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Let's break down each component:
Header
The header typically consists of two parts: the token type (which is JWT) and the signing algorithm being used, such as HMAC SHA256 or RSA. This information tells the receiving party how to process and verify the token.
A decoded header looks like this:
{
"alg": "HS256",
"typ": "JWT"
}
Payload
The payload contains the claims—statements about an entity (typically the user) and additional metadata. Claims are categorized into three types:
| Claim Type | Description | Examples |
|---|---|---|
| Registered Claims | Predefined claims recommended by the JWT specification | iss, exp, sub, aud |
| Public Claims | Custom claims defined by those using JWTs, should be collision-resistant | name, email, role |
| Private Claims | Custom claims agreed upon between parties | department, permissions |
A typical payload might look like:
{
"sub": "1234567890",
"name": "John Doe",
"email": "[email protected]",
"role": "admin",
"iat": 1516239022,
"exp": 1516242622
}
Signature
The signature is the cryptographic seal that ensures the token hasn't been tampered with. It's created by taking the encoded header, encoded payload, a secret key, and applying the algorithm specified in the header.
For example, if using HMAC SHA256, the signature is created like this:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
The signature allows the recipient to verify that the sender of the JWT is who it says it is and that the message wasn't changed along the way.
Why Use a JSON Web Token Decoder?
While JWTs are designed to be machine-readable, developers frequently need to inspect their contents during development, debugging, and security auditing. A JWT decoder transforms the Base64-encoded strings into human-readable JSON, making it easy to understand what information the token contains.
Here are the primary reasons developers use JWT decoders:
Development and Debugging
When building authentication systems, you need to verify that your tokens contain the correct claims and are properly formatted. A decoder lets you quickly inspect tokens without writing custom code or using command-line tools.
For instance, if users report authentication issues, you can decode their JWT to check if the exp (expiration) claim has passed or if required claims are missing.
Security Auditing
Security teams use JWT decoders to analyze tokens for potential vulnerabilities. They can check for:
- Sensitive information inadvertently included in the payload
- Weak signing algorithms (like
noneorHS256whenRS256is expected) - Missing or improperly configured security claims
- Excessive token lifetimes that increase security risk
Integration Testing
When integrating with third-party APIs that use JWT authentication, decoding tokens helps you understand the expected format and claims structure. This is especially useful when documentation is incomplete or outdated.
Learning and Education
For developers new to JWT, a decoder provides immediate visual feedback on how the three-part structure works and how changes to the payload affect the final token.
Quick tip: Never paste production JWTs containing real user data into online decoders. Use our JWT Decoder tool which processes tokens entirely in your browser without sending data to any server.
Step-by-Step Decoding Process
Decoding a JWT is straightforward once you understand the process. Here's how it works under the hood:
Step 1: Split the Token
First, split the JWT string at the period characters to separate the three parts:
const parts = token.split('.');
const header = parts[0];
const payload = parts[1];
const signature = parts[2];
Step 2: Base64 Decode
Each part is Base64URL encoded (a URL-safe variant of Base64). Decode the header and payload to get the JSON strings:
const decodedHeader = atob(header);
const decodedPayload = atob(payload);
Step 3: Parse JSON
Parse the decoded strings as JSON objects:
const headerObj = JSON.parse(decodedHeader);
const payloadObj = JSON.parse(decodedPayload);
Step 4: Inspect the Contents
Now you can examine the claims and metadata. Check for standard claims like:
iss(issuer): Who created and signed the tokensub(subject): The user or entity the token representsaud(audience): Who the token is intended forexp(expiration): When the token expires (Unix timestamp)iat(issued at): When the token was creatednbf(not before): Token shouldn't be accepted before this time
Using our JWT Decoder, this entire process happens instantly in your browser. Simply paste your token and see the decoded header and payload immediately.
Validating the Token's Signature
Decoding a JWT is only half the story—validation is where security happens. Anyone can decode a JWT since it's just Base64-encoded JSON, but only parties with the correct secret or public key can verify the signature.
Why Signature Validation Matters
The signature ensures two critical security properties:
- Integrity: The token hasn't been modified since it was signed
- Authenticity: The token was created by a trusted party who possesses the secret key
Without signature validation, an attacker could decode a JWT, change the payload (perhaps elevating their privileges from "user" to "admin"), re-encode it, and use the modified token. The signature prevents this attack.
Validation Process
To validate a JWT signature, you need:
- The complete JWT (all three parts)
- The secret key (for HMAC algorithms) or public key (for RSA/ECDSA algorithms)
- Knowledge of the signing algorithm used
The validation process recreates the signature using the header and payload from the token, then compares it to the signature included in the token. If they match, the token is valid.
Pro tip: Always validate JWTs on the server side, never trust client-side validation alone. Attackers can bypass client-side checks, but they can't forge a valid signature without the secret key.
Common Signing Algorithms
| Algorithm | Type | Key Type | Use Case |
|---|---|---|---|
HS256 |
HMAC with SHA-256 | Symmetric (shared secret) | Simple applications, same party creates and verifies |
RS256 |
RSA with SHA-256 | Asymmetric (public/private key pair) | Distributed systems, multiple verifiers |
ES256 |
ECDSA with SHA-256 | Asymmetric (elliptic curve) | Performance-critical applications, smaller signatures |
none |
No signature | None | Never use in production! |
Additional Validation Checks
Beyond signature verification, always validate:
- Expiration (
exp): Reject tokens past their expiration time - Not Before (
nbf): Reject tokens used before they're valid - Issuer (
iss): Verify the token comes from a trusted source - Audience (
aud): Ensure the token is intended for your application
Security Considerations and Best Practices
JWTs are powerful but require careful handling to maintain security. Here are essential best practices every developer should follow:
Never Store Sensitive Data in JWTs
Remember: JWTs are encoded, not encrypted. Anyone can decode them and read the payload. Never include:
- Passwords or password hashes
- Credit card numbers or financial data
- Social security numbers or national IDs
- Private API keys or secrets
Instead, store only non-sensitive identifiers and use those to look up sensitive data from a secure database when needed.
Use Strong Secrets and Key Management
For HMAC algorithms, use cryptographically random secrets at least 256 bits long. Store secrets securely using environment variables or dedicated secret management services like AWS Secrets Manager or HashiCorp Vault.
Never hardcode secrets in your source code or commit them to version control.
Set Appropriate Expiration Times
Short-lived tokens reduce the window of opportunity for attackers. Consider:
- Access tokens: 15 minutes to 1 hour
- Refresh tokens: Days to weeks, stored securely
- Email verification tokens: 24 hours
Implement refresh token rotation for enhanced security—issue a new refresh token each time one is used and invalidate the old one.
Implement Token Revocation
While JWTs are stateless, you still need a way to revoke compromised tokens. Common approaches include:
- Maintaining a blocklist of revoked token IDs (using
jticlaim) - Storing token version numbers and incrementing on password change
- Using short expiration times with refresh tokens that can be revoked
Validate Algorithm Headers
Always explicitly specify which algorithms your application accepts. Reject tokens using unexpected algorithms to prevent algorithm confusion attacks.
// Good: Explicitly specify allowed algorithms
jwt.verify(token, secret, { algorithms: ['RS256'] });
// Bad: Accept any algorithm
jwt.verify(token, secret);
Pro tip: Use our Password Generator to create strong secrets for HMAC signing, and our Hash Generator to create token IDs for revocation tracking.
Common JWT Issues and Solutions
Even experienced developers encounter JWT-related problems. Here are the most common issues and how to resolve them:
Issue 1: "Invalid Signature" Errors
Symptoms: Token validation fails with signature mismatch errors.
Common Causes:
- Using the wrong secret key for validation
- Token was modified after signing
- Algorithm mismatch between signing and verification
- Whitespace or encoding issues when copying tokens
Solutions:
- Verify you're using the exact same secret that was used to sign the token
- Check that the algorithm in the header matches your validation code
- Ensure no whitespace or line breaks were added when copying the token
- Use our JWT Decoder to inspect the header and verify the algorithm
Issue 2: Token Expired
Symptoms: Authentication fails with "token expired" or "exp claim validation failed" messages.
Common Causes:
- Token's
expclaim is in the past - Clock skew between servers
- Tokens cached on client side past expiration
Solutions:
- Implement automatic token refresh before expiration
- Add clock skew tolerance (typically 30-60 seconds) in validation
- Clear cached tokens when they expire
- Synchronize server clocks using NTP
Issue 3: Token Too Large
Symptoms: HTTP headers exceed size limits, cookies too large, or performance degradation.
Common Causes:
- Including too much data in the payload
- Storing arrays or complex objects in claims
- Adding unnecessary custom claims
Solutions:
- Store only essential identifiers in the token
- Use token ID to look up additional data from database
- Remove redundant or unnecessary claims
- Consider using reference tokens for complex authorization scenarios
Issue 4: CORS Errors with JWT Authentication
Symptoms: Browser blocks requests with JWT in Authorization header due to CORS policy.
Solutions:
- Configure server to include proper CORS headers
- Add
AuthorizationtoAccess-Control-Allow-Headers - Handle preflight OPTIONS requests correctly
- Consider using cookies with
SameSiteattribute for same-origin scenarios
Issue 5: XSS and Token Storage Vulnerabilities
Symptoms: Tokens stolen through cross-site scripting attacks.
Solutions:
- Never store JWTs in localStorage (vulnerable to XSS)
- Use httpOnly cookies for web applications when possible
- Implement Content Security Policy (CSP) headers
- Sanitize all user input to prevent XSS
- For SPAs, consider storing tokens in memory only
JWT vs. Traditional Session Authentication
Understanding when to use JWTs versus traditional sessions is crucial for building secure, scalable applications. Each approach has distinct advantages and trade-offs.
Traditional Session Authentication
In session-based authentication, the server creates a session after successful login and stores session data (user ID, permissions, etc.) in server memory or a database. The client receives a session ID, typically stored in a cookie.
Advantages:
- Easy to revoke—simply delete the session from storage
- Smaller cookie size (just a session ID)
- Sensitive data never leaves the server
- Simpler to implement for traditional web applications
Disadvantages:
- Requires server-side storage and state management
- Difficult to scale horizontally without sticky sessions or shared storage
- Not ideal for microservices or distributed systems
- Requires database lookup on every request
JWT Authentication
With JWTs, all necessary information is contained in the token itself. The server validates the signature but doesn't need to store session data.
Advantages:
- Stateless—no server-side session storage required
- Scales horizontally easily
- Perfect for microservices and distributed systems
- Works seamlessly across different domains
- Reduces database load (no session lookups)
Disadvantages:
- Difficult to revoke before expiration
- Larger size than session IDs
- Data in payload is visible (though signed)
- Requires careful security implementation
When to Use Each Approach
Use JWTs when:
- Building APIs consumed by mobile apps or SPAs
- Implementing microservices architecture
- Need to scale horizontally without shared state
- Working with third-party integrations
- Implementing Single Sign-On (SSO)
Use sessions when:
- Building traditional server-rendered web applications
- Need immediate revocation capability
- Working with highly sensitive data
- Have a single monolithic application
- Want simpler security model
Hybrid approach: Many modern applications use both—short-lived JWTs for API access and longer-lived refresh tokens stored as httpOnly cookies, combining the benefits of both approaches.
Real-World Use Cases and Examples
Let's explore practical scenarios where JWTs solve real authentication and authorization challenges.
Example 1: Mobile App Authentication
A fitness tracking app needs to authenticate users and allow them to sync data across devices without maintaining server sessions.
Implementation:
- User logs in with credentials
- Server validates credentials and issues a JWT containing user ID and subscription tier
- Mobile app stores JWT securely in device keychain
- Each API request includes JWT in Authorization header
- Server validates signature and extracts user ID from token
- Token expires after 7 days, requiring re-authentication
Sample JWT payload:
{
"sub": "user_12345",
"email": "[email protected]",
"subscription": "premium",
"iat": 1711900800,
"exp": 1712505600
}
Example 2: Microservices Authorization
An e-commerce platform with separate services for users, products, orders, and payments needs to authorize requests across services.
Implementation:
- API gateway authenticates user and issues JWT with permissions
- JWT includes user role and specific permissions
- Each microservice validates JWT signature independently
- Services make authorization decisions based on claims
- No inter-service communication needed for authentication
Sample JWT payload:
{
"sub