How to Decode JWT Tokens Online: Complete Security Guide

Building a RAG system? Diagnose failures automatically at rag-debugger.pages.dev →

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:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

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 Now

JWT 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 Free

Related Reading: