Skip to main content
The JWT Debugger tool decodes JSON Web Tokens (JWTs) to inspect their header, payload claims, and expiration status. It provides a clear breakdown of token contents without requiring signature verification, making it ideal for debugging authentication flows.

Features

  • Decode JWT header and payload
  • Display all claims in formatted JSON
  • Automatic expiration validation
  • ISO 8601 expiration timestamp
  • Algorithm detection (HS256, RS256, etc.)
  • No signature verification (inspection only)

Use Cases

Authentication Debugging

Inspect JWT tokens to verify claims and troubleshoot authentication issues

Token Expiration

Check when a token expires and whether it’s still valid

Claims Analysis

Review user permissions, roles, and metadata stored in the token

Integration Testing

Validate token structure during API integration development

JWT Structure

A JWT consists of three Base64-encoded parts separated by dots:
header.payload.signature
Contains token metadata:
{
  "alg": "HS256",
  "typ": "JWT"
}

Payload

Contains claims (user data, permissions, etc.):
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}

Signature

Used to verify token authenticity (not decoded by this tool).

Input Format

Paste the complete JWT token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
The tool requires at least the header and payload segments. The signature segment is optional.

Output Format

The tool displays:
  1. Header - Algorithm and token type
  2. Payload - All claims in formatted JSON
  3. Expiration - ISO timestamp and validity status
// Header
{
  "alg": "HS256",
  "typ": "JWT"
}

// Payload
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}

// Expires At: 2024-03-15T10:30:22.000Z
// Expired: false

Examples

Decode a simple JWT with standard claims.Input:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyNDI2MjJ9.4Adcj0prp8-5hNbzH4K6cJZmRlvJG9xMhH5C2VKhAJg
Output:
// Header
{
  "alg": "HS256",
  "typ": "JWT"
}

// Payload
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}

// Expires At: 2018-01-18T01:30:22.000Z
// Expired: true

Standard Claims

Registered Claims (RFC 7519)

ClaimNameDescription
issIssuerWho created the token
subSubjectUser/principal identifier
audAudienceIntended recipient(s)
expExpirationUnix timestamp when token expires
nbfNot BeforeToken not valid before this time
iatIssued AtWhen token was created
jtiJWT IDUnique token identifier

Custom Claims

Applications often add custom claims:
{
  "email": "user@example.com",
  "name": "Alice Smith",
  "roles": ["admin"],
  "tenant_id": "org_123",
  "permissions": ["read:users", "write:users"]
}

Implementation Details

From lib/tools/engine.ts:424-436:
case 'jwt-debugger': {
  const token = input.trim();
  const [headSegment, payloadSegment] = token.split('.');
  if (!headSegment || !payloadSegment) 
    return { output: 'Invalid JWT' };
    
  const decodeSegment = (segment: string) => 
    JSON.parse(atob(segment.replaceAll('-', '+').replaceAll('_', '/')));
    
  const header = decodeSegment(headSegment);
  const { jwtDecode } = await import('jwt-decode');
  const payload = jwtDecode<Record<string, unknown>>(token);
  
  const exp = typeof payload.exp === 'number' 
    ? new Date(payload.exp * 1000) 
    : null;
    
  return {
    output: `// Header\n${stringify(header, true)}\n\n// Payload\n${stringify(payload, true)}\n\n// Expires At: ${exp ? exp.toISOString() : 'N/A'}\n// Expired: ${exp ? exp.getTime() < Date.now() : 'N/A'}`,
  };
}

Base64 Decoding

JWT uses URL-safe Base64 encoding:
  • +-
  • /_
  • Padding = removed
The tool automatically handles both standard and URL-safe variants.

Common Patterns

Extract from Authorization Header

Remove the “Bearer” prefix:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
                      ^^^ Paste this part only

Check Token Expiration

Compare exp claim to current time:
const payload = JSON.parse(atob(token.split('.')[1]));
const expiresAt = new Date(payload.exp * 1000);
const isExpired = Date.now() > expiresAt.getTime();

Validate Algorithm

Check the alg header claim:
{
  "alg": "HS256"  // HMAC SHA-256 (symmetric)
  "alg": "RS256"  // RSA SHA-256 (asymmetric)
  "alg": "ES256"  // ECDSA SHA-256 (asymmetric)
}
Never trust "alg": "none" tokens in production. This disables signature verification.

Security Considerations

This tool DOES NOT verify signatures. It only decodes the token for inspection. Always verify signatures server-side before trusting token contents.

What This Tool Does

  • ✅ Decodes Base64 header and payload
  • ✅ Parses claims and displays them
  • ✅ Checks expiration timestamp

What This Tool Does NOT Do

  • ❌ Verify cryptographic signatures
  • ❌ Validate issuer or audience
  • ❌ Check token revocation
  • ❌ Enforce any security policies

Best Practices

  1. Never store secrets in JWT payloads - They are not encrypted, only encoded
  2. Use short expiration times - 15 minutes for access tokens, longer for refresh tokens
  3. Verify signatures - Always validate tokens server-side
  4. Use HTTPS - Tokens can be intercepted over unencrypted connections
  5. Rotate secrets - Change signing keys periodically