Make Tools
2026-04-01

JWT Decoding and Security Validation Guide

Understand JSON Web Tokens from the inside out. Learn to decode JWTs, validate signatures, spot security issues, and debug authentication flows.

JWTAuthenticationSecurity

What Is a JWT?

A JSON Web Token (JWT) is a compact, URL-safe token format used for securely transmitting claims between parties. JWTs are the standard for API authentication, OAuth 2.0 flows, and single sign-on (SSO) systems. Every JWT is a string of three Base64URL-encoded parts separated by dots:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.D4W0BvPYBOmJ1iKtHqTnpUJfXbL_Cz8
  • Header — algorithm and token type
  • Payload — the claims (user data, permissions, expiration)
  • Signature — verification that the token hasn't been tampered with

Anatomy of a JWT

The Header

The header specifies the signing algorithm and token type:

{
  "alg": "HS256",
  "typ": "JWT"
}

Common algorithms include HS256 (HMAC-SHA256), RS256 (RSA), ES256 (ECDSA), and PS256 (RSA-PSS). The alg field tells the verifier which algorithm to expect.

The Payload

The payload contains claims — statements about an entity (typically the user) and additional metadata:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "iat": 1712275200,
  "exp": 1712278800
}

Registered Claims

  • iss (issuer) — who issued the token
  • sub (subject) — the user or entity ID
  • aud (audience) — intended recipient(s)
  • exp (expiration) — timestamp after which the token is invalid
  • nbf (not before) — timestamp before which the token is invalid
  • iat (issued at) — when the token was created
  • jti (JWT ID) — unique identifier for the token

Decoding JWTs

Decoding a JWT simply means Base64URL-decoding the header and payload. This does not verify the signature — anyone can decode a JWT without knowing the secret.

Our JWT Decoder instantly parses any JWT, showing the decoded header, payload, and expiration status. Paste a token and see its contents in real time.

Decoding in Code

// JavaScript (manual decode, no verification)
function decodeJWT(token) {
  const [header, payload] = token.split('.');
  return {
    header: JSON.parse(atob(header.replace(/-/g, '+').replace(/_/g, '/'))),
    payload: JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/')))
  };
}
# Python with PyJWT (with verification)
import jwt
decoded = jwt.decode(token, key="your-secret", algorithms=["HS256"])

Signature Verification

The signature is what makes a JWT trustworthy. It's computed from the header, payload, and a secret (HMAC) or private key (RSA/ECDSA):

HMAC-SHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

If even one character in the header or payload changes, the signature won't match. This is how you detect tampering.

Why Verification Matters

A JWT without signature verification is just a JSON object anyone can forge.

A common vulnerability: applications decode JWTs and trust the payload without verifying the signature. An attacker can modify the "sub" claim to impersonate another user, change "admin": false to "admin": true, or extend the "exp" timestamp.

Common Security Vulnerabilities

Algorithm Confusion (alg:none)

Some libraries accept "alg": "none" — a token with no signature at all. Attackers strip the signature and set the algorithm to "none," and vulnerable servers accept the forged token.

// Malicious token — no signature
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NSIsImFkbWluIjp0cnVlfQ.

Fix: Always explicitly specify which algorithms your server accepts. Never use the algorithm from the token header.

Algorithm Switching (HS256 → RS256)

An attacker takes a token signed with RS256 (public/private key) and re-signs it using HS256 with the public key as the HMAC secret. If the server doesn't enforce the expected algorithm, it may verify the forged token using the public key as an HMAC secret.

Fix: Maintain a whitelist of allowed algorithms per endpoint.

Weak Secrets

HMAC-signed JWTs are only as strong as the secret. Short or guessable secrets can be brute-forced. Tools like jwt_tool can crack weak HS256 secrets using dictionary attacks.

Fix: Use at least 256-bit random secrets. Prefer RS256 or ES256 for distributed systems where the signing key shouldn't be shared.

Missing Expiration

A JWT without an exp claim never expires. If stolen, it grants access forever. Always set exp — typically 15 minutes to 1 hour for access tokens.

Refresh Tokens and Token Rotation

Short-lived access tokens paired with long-lived refresh tokens is the standard pattern:

  1. User authenticates → receives access token (15 min) + refresh token (7 days)
  2. Access token expires → client sends refresh token to get a new access token
  3. Refresh token is stored securely (httpOnly cookie) and rotated on each use

This limits the damage window if an access token is compromised.

JWT Best Practices

  • Always verify the signature before trusting any claim.
  • Validate exp, nbf, iss, and aud claims.
  • Use strong algorithms: RS256 or ES256 for asymmetric, HS256 with a strong secret for symmetric.
  • Never store JWTs in localStorage — use httpOnly cookies to prevent XSS theft.
  • Keep payloads small — JWTs are sent with every request. Large payloads increase bandwidth.
  • Implement token revocation for logout and compromised tokens (blocklist or short expiry).

Debugging JWTs in the Wild

When debugging authentication issues, you often need to inspect tokens from logs, API responses, or browser storage. Copy the token string and paste it into our JWT Decoder to instantly see:

  • Decoded header with algorithm details
  • All payload claims with human-readable timestamps
  • Expiration status (expired, valid, or missing)
  • Signature validity (when the secret is provided)

Conclusion

JWTs are powerful but require careful handling. Decode them freely to understand what data they carry, but never trust a JWT without verifying its signature. Stay aware of algorithm confusion attacks, use strong secrets, keep expiration times short, and test your implementation thoroughly. Our JWT Decoder is your first step in understanding any token you encounter.

Ready to try it?

Open Tool →