JWT Decoder

Decode and inspect JSON Web Tokens (JWT) instantly. View header, payload, and verify expiration. All processing happens locally in your browser.

🔴 Header

Paste a JWT to see the header

🟣 Payload

Paste a JWT to see the payload

🔵 Signature

Paste a JWT to see the signature

⚠️ Signature cannot be verified without the secret/public key

📐 JWT Structure

Header . Payload . Signature

Header: Algorithm & token type (e.g., HS256, RS256)

Payload: Claims (user data, expiration, permissions)

Signature: Encrypted hash to verify authenticity

📋 Common JWT Claims

sub

Subject (user identifier)

iss

Issuer (who created the token)

aud

Audience (intended recipient)

exp

Expiration time (Unix timestamp)

iat

Issued at (creation time)

nbf

Not before (token not valid before)

The Day a JWT Bug Cost Us 3 Hours of Sleep

It was 11 PM on a Friday when the support tickets started flooding in. "Can't login." "Session expired immediately." "Getting kicked out constantly." Our authentication was completely broken, and we had no idea why.

Two hours of frantic debugging later, I copied a JWT from a failed request, pasted it into a decoder, and there it was: the exp claim was set to a date in 1970. Someone had passed seconds instead of milliseconds to the timestamp function. The token was expiring 50 years ago.

That's when I truly understood why every developer needs a JWT decoder in their toolkit. Not just for debugging emergencies, but for everyday API development.

What Is a JWT, Really?

A JSON Web Token (JWT, pronounced "jot") is a compact, URL-safe way to represent claims between two parties. In plain English: it's a secure way to pass information that can be verified and trusted.

The concept originated from the need to handle authentication in distributed systems. Traditional sessions required server-side storage—every request needed to hit a database or cache to verify the session. JWTs flip this: they contain everything needed for verification within the token itself.

JWTs have three parts, separated by dots:

  1. Header: The algorithm used and token type (usually "JWT")
  2. Payload: The actual data (claims about the user)
  3. Signature: The verification hash that proves the token wasn't tampered with

Here's the key insight that trips up many developers: the header and payload are only Base64-encoded, not encrypted. Anyone can decode them. The signature is what prevents tampering—if you change even one character in the payload, the signature won't match.

⚠️ Security Warning:

Never put sensitive data in JWT payloads (passwords, credit cards, social security numbers). The payload is encoded, not encrypted—anyone with the token can read it. JWTs are for claims ("this user has admin rights"), not secrets.

📖 Developer Story #1: The Microservices Migration

Background: A fintech team was migrating from a monolith to microservices. Their old session-based auth required a central Redis cluster for session storage. Every request hit Redis.

The Problem: Every microservice needed to check the session store. Redis became a bottleneck—99th percentile latency spiked during peak hours. Cache invalidation caused subtle bugs. Scaling meant scaling Redis, which was expensive.

The Solution: Switch to JWT authentication with RS256 (asymmetric signing). Each service received the public key and could verify tokens independently. No central store needed.

Result: Redis load dropped 80%. Auth latency went from 15ms to 2ms. Services became truly independent—you could deploy them anywhere without worrying about Redis connectivity.

How JWT Authentication Actually Works

Let me walk through the complete flow, because understanding this is essential for debugging:

1. Login Request

User sends credentials (email/password) to your auth server. The server validates against the database, probably checking a hashed password.

2. Token Generation

If credentials are valid, the server creates a JWT. It builds a payload with claims like:

{
  "sub": "user-123",
  "email": "user@example.com",
  "role": "admin",
  "iat": 1703980800,
  "exp": 1704067200
}

Then it signs this with the secret key (HS256) or private key (RS256).

3. Token Delivery

The JWT is sent back to the client. Best practice: use an httpOnly cookie for the refresh token, and keep the access token in memory (not localStorage—that's vulnerable to XSS).

4. Authenticated Requests

Client includes the JWT in the Authorization header: Bearer eyJhbGc.... Every request carries this token.

5. Server Verification

The receiving server verifies the signature (using the secret or public key), checks that the token isn't expired, and reads the claims. No database lookup needed—everything is in the token.

📖 Developer Story #2: The OAuth Integration Nightmare

Background: A SaaS company was integrating "Sign in with Google" using OAuth 2.0. They received an ID token (which is a JWT) from Google after successful authentication.

The Problem: Users were randomly getting "Invalid token" errors. Some worked, some didn't. The development team spent days checking their OAuth flow, scopes, and callback URLs.

The Solution: They decoded the failing tokens and discovered the aud (audience) claim didn't match their client ID. Google was returning tokens intended for a different app—their staging environment's client ID had leaked into production config.

Result: Fixed a config file. Five days of debugging solved in 30 seconds once they knew to check the audience claim. They now decode every token during debugging as step one.

JWT Algorithms: HS256 vs RS256

This is where security architecture decisions happen. The algorithm you choose has real implications:

HS256 (HMAC with SHA-256)

  • Type: Symmetric—same secret for signing and verifying
  • Pros: Faster, simpler, smaller keys
  • Cons: Every service that verifies needs the secret
  • Best for: Single-service applications, internal APIs

RS256 (RSA Signature with SHA-256)

  • Type: Asymmetric—private key signs, public key verifies
  • Pros: Only auth server needs the private key; public key can be shared freely
  • Cons: Slower, larger keys, more complex setup
  • Best for: Microservices, third-party integrations, OAuth

💡 Pro Tip:

If multiple services need to verify tokens, use RS256. Sharing a symmetric secret across services increases your attack surface. With RS256, compromising a verifying service doesn't compromise token generation.

Common JWT Security Vulnerabilities

Over the years, I've seen (and sometimes caused) various JWT-related security issues. Here are the ones that keep showing up:

The "alg: none" Attack

Some JWT libraries accept tokens with "alg": "none", meaning "this token has no signature, trust it anyway." Attackers could forge tokens by setting this algorithm. Modern libraries reject this, but always verify yours does.

Algorithm Confusion

If your server expects RS256 but accepts HS256, an attacker could use your public key (which is, well, public) as the HS256 secret. Some libraries allowed this switch. Always explicitly specify which algorithm your server accepts.

Weak Secrets

For HS256, a weak secret can be brute-forced. Use at least 256 bits of cryptographic randomness. "secret123" is not a secret—it's the first thing attackers try.

Long Expiration Times

JWTs can't be revoked (easily). A token valid for a year means a stolen token is valid for a year. Keep access tokens short-lived (15 minutes to 1 hour) and use refresh tokens for longer sessions.

📖 Developer Story #3: The Security Audit Wake-Up Call

Background: A healthcare startup passed their first external security audit, but barely. The auditors flagged their JWT implementation as "high risk."

The Problems: Access tokens expired in 30 days. The HS256 secret was only 20 characters. Tokens were stored in localStorage (XSS vulnerable). The library didn't reject "alg: none".

The Solution: Complete overhaul. Moved to RS256, 15-minute access tokens, httpOnly cookie refresh tokens, and upgraded the JWT library. Implemented token blacklisting for password changes.

Result: Passed the next audit with no findings. More importantly, they now understood why each decision mattered—security wasn't just a checklist, it was architecture.

Debugging JWTs: A Systematic Approach

When authentication fails, here's my debugging checklist:

1. Decode the Token

First, just see what's in it. Use this tool—paste the token, check the payload. Does it contain what you expect?

2. Check Expiration

Is exp in the future? Is it reasonable? Watch for timezone issues (all JWT timestamps should be UTC) and unit confusion (seconds vs milliseconds).

3. Verify the Algorithm

Does the header's alg match what your server expects? Mismatches cause signature verification failures.

4. Check Audience and Issuer

If your server validates aud and iss, do the values match your configuration? This catches cross-environment token issues.

5. Look for Missing Claims

Does your server require certain claims (sub, roles, etc.)? Are they present? Null or missing values cause subtle authorization bugs.

6. Check Token Size

JWTs with many claims get large. Some servers have header size limits. If your token is over 4KB, you might hit issues with proxies or CDNs.

JWT vs Sessions: An Honest Comparison

JWTs aren't always the right choice. Here's when each approach works best:

Aspect JWT Sessions
Stateless ✅ Yes, self-contained ❌ No, needs session store
Revocation ❌ Must wait for expiry or implement blacklist ✅ Instant, just delete session
Size Larger (500 bytes - several KB) Small (~32 bytes session ID)
Cross-domain ✅ Easy with Authorization header ❌ Cookie domain restrictions
Microservices ✅ No shared state needed ❌ Need sticky sessions or shared store
Mobile apps ✅ Natural fit ❌ Cookie management is messy

Use JWTs for: APIs consumed by mobile apps, microservices architectures, cross-domain authentication, OAuth/OpenID Connect.

Use sessions for: Traditional web apps, situations requiring instant revocation (admin account compromise), simple single-server deployments.

How This Tool Works

When you paste a JWT, the tool:

  1. Splits the token into three parts at the dots
  2. Base64URL-decodes the header and payload (handling the URL-safe alphabet)
  3. Parses the JSON and pretty-prints it with syntax highlighting
  4. Converts Unix timestamps to human-readable dates in your timezone
  5. Calculates whether the token is expired based on the exp claim

Everything happens in your browser using JavaScript. Your tokens are never sent to any server. This is critical—production JWTs often contain sensitive claims and should never be pasted into tools that might log them.

✅ Best Practice:

Bookmark this tool for debugging. The next time auth breaks—and it will—start by decoding the token. Nine times out of ten, the answer is visible in the claims.

Final Thoughts

JWTs are everywhere in modern web development. They're in your API authentication. They're in OAuth flows. They're in the ID tokens from social logins. Understanding them—how they work, what they contain, what can go wrong—is essential for any developer working with web services.

The decoder above is simple by design. It shows you what's in the token, nothing more. But that's often all you need. When authentication breaks at midnight, being able to instantly see what's actually in the token—what the expiration is, what claims are present, which algorithm is used—that's the difference between a quick fix and an all-night debugging session.

Keep this bookmarked. You'll use it more than you expect.

Frequently Asked Questions

AK

About the Author

Ankush Kumar Singh is a digital tools researcher and UI problem-solver who writes practical tutorials about productivity, text processing, and online utilities.