JWT Decoder: How to Read, Debug, and Secure JSON Web Tokens

Multi-Toolkit Team8 min read
Developer ToolsSecurityAuthenticationJWT

A JWT (JSON Web Token) is showing up everywhere — in Authorization headers, cookies, query strings, and webhook payloads. When it works, you barely notice it. When it doesn't, the error is usually cryptic: 401 Unauthorized, invalid signature, or just nothing. This guide gives you the tools to decode, inspect, and fix any JWT fast.

What Is a JWT, Exactly?

A JWT is three Base64url-encoded strings joined by dots: header.payload.signature. Each dot is a section boundary. The header and payload are just JSON objects — anyone can read them. The signature is the only part that requires a secret key.

The header contains the algorithm (alg) and token type (typ). The payload contains claims — facts about the user or session, like sub (user ID), exp (expiration time), and roles. The signature is computed from the header + payload using a secret key, so any tampering with the payload invalidates it.

Key insight: JWTs are integrity-protected, not encrypted. Anyone with the token can read the payload. Never put secrets or sensitive PII inside a JWT payload.

How to Decode a JWT

Base64url is Base64 with + replaced by -, / replaced by _, and padding removed. To decode in any language:

// JavaScript
const [headerB64, payloadB64] = token.split('.');
const header  = JSON.parse(atob(headerB64.replace(/-/g,'+').replace(/_/g,'/')));
const payload = JSON.parse(atob(payloadB64.replace(/-/g,'+').replace(/_/g,'/')));

# Python
import base64, json
parts = token.split('.')
header  = json.loads(base64.urlsafe_b64decode(parts[0] + '=='))
payload = json.loads(base64.urlsafe_b64decode(parts[1] + '=='))

Or paste the token into our JWT Decoder to get a formatted, annotated breakdown instantly.

Standard JWT Claims Explained

The JWT spec defines these registered claims:

  • sub — Subject: who the token is about (usually a user ID)
  • iss — Issuer: which auth server issued the token
  • aud — Audience: which service the token is intended for
  • exp — Expiration: Unix timestamp after which the token is invalid
  • iat — Issued At: when the token was created
  • nbf — Not Before: token is invalid before this timestamp
  • jti — JWT ID: unique identifier to prevent replay attacks

Missing exp means the token never expires — a security risk. Missing iss and aud means the token can be replayed across services.

JWT Security Vulnerabilities to Know

1. Algorithm None

A JWT with "alg": "none" has no signature. An attacker can craft any payload, remove the signature, and set alg to "none". If your server accepts it, authentication is completely bypassed. Our decoder flags this as Critical. Always reject alg: none on the server.

2. HS256 vs RS256

HS256 uses a single symmetric key — whoever can verify a token can also forge one. In a microservices architecture where multiple services need to verify tokens, sharing an HS256 key creates many attack surfaces. RS256 uses an asymmetric key pair: the private key signs, the public key verifies. Only the auth server needs the private key.

3. Accepting the Wrong Algorithm

A classic attack: the attacker knows your HS256 public key, creates an HS256 JWT signed with that key, then sends it to a server expecting RS256 tokens. If the library naively uses the key from the JWT header's alg field without validation, it verifies the forged token. Always specify the expected algorithm explicitly in your validation code.

4. Expired Tokens

The most common JWT bug: tokens expire and the client doesn't refresh them. Check the exp claim in your decoder. If it's in the past, the token is invalid. Implement a refresh token flow with short-lived access tokens (15m–1h) and longer refresh tokens (7–30 days) stored in HttpOnly cookies.

Debugging a JWT Auth Failure

When you see a 401 with a JWT, check these in order:

  1. Paste the token into the JWT Decoder — is it structurally valid?
  2. Check exp — is the token expired?
  3. Check alg — does it match what your server expects?
  4. Check iss — does the issuer match your auth provider's URL?
  5. Check aud — does the audience match your API identifier?
  6. Check nbf — is the clock skewed between client and server?
  7. Verify the signature on your server with the correct key — are you using the right JWKS endpoint?

Best Practices Summary

  • Use RS256 or ES256 for distributed systems — symmetric HS256 only for single-server setups
  • Always set exp, iss, and aud claims
  • Set short expiration for access tokens (15m–1h); use refresh tokens for longer sessions
  • Store access tokens in memory; refresh tokens in HttpOnly cookies
  • Explicitly allowlist the algorithms your server accepts — never derive it from the token
  • Rotate signing keys periodically and publish them via a JWKS endpoint

Ready to inspect your JWT?

Decode Your JWT →

← Back to all articles