What Is a JWT?
A JSON Web Token (JWT) is an open standard (RFC 7519) for securely transmitting information between parties. It's the most widely used stateless authentication mechanism in modern web applications.
A JWT consists of three Base64URL-encoded parts separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4iLCJpYXQiOjE1MTYyMzkwMjJ9.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT Structure: Three Parts
- Header: Token type (JWT) and signing algorithm (HS256, RS256, etc.)
{"alg": "HS256", "typ": "JWT"}
- Payload: Claims — the data being transmitted, such as user ID, roles, expiration
{"sub": "1234567890", "name": "John", "exp": 1716076800}
- Signature: HMAC or RSA signature over Header + Payload — proves the token hasn't been tampered with
Important: The payload is only Base64-encoded, not encrypted. Anyone can decode and read it. Never store passwords or sensitive personal data in JWT payloads.
How to Use the JWT Debugger
Use tool.tl's JWT debugger:
- Go to tool.tl/jwt-debugger
- Paste your JWT token into the input field
- The tool decodes and displays the Header and Payload instantly — no secret key needed for decoding
- Optionally enter your secret/public key to verify the signature
All decoding happens locally in your browser — the token is never sent to a server.
Standard JWT Claims
| Claim | Meaning | Example |
sub | Subject — token principal (usually user ID) | "user_123" |
exp | Expiration time (Unix timestamp) | 1716076800 |
iat | Issued At — when the token was created | 1716073200 |
iss | Issuer — who created the token | "api.example.com" |
aud | Audience — who the token is intended for | "frontend-app" |
jti | JWT ID — unique identifier for replay attack prevention | "abc123" |
Common JWT Security Vulnerabilities
- Algorithm confusion attack: Early JWT libraries allowed setting algorithm to "none" to bypass signature verification. Always enforce allowed algorithms server-side and reject "none"
- Weak secret keys: HS256 uses a symmetric key — if leaked, attackers forge any token. Use RS256 (asymmetric) for production systems where the public key can be distributed safely
- Long expiry times: Tokens valid for 30 days increase theft risk. Use short-lived access tokens (1–24 hours) with refresh token rotation
- Sensitive data in payload: Payload is encoded, not encrypted — never store passwords, SSNs, or private data in JWT claims
JWT in Code
# Python (PyJWT)
import jwt
token = jwt.encode({"sub": "user_123", "exp": 1716076800}, "secret", algorithm="HS256")
data = jwt.decode(token, "secret", algorithms=["HS256"])
// JavaScript (jsonwebtoken)
const jwt = require('jsonwebtoken');
const token = jwt.sign({ sub: 'user_123' }, 'secret', { expiresIn: '1h' });
const data = jwt.verify(token, 'secret');
Frequently Asked Questions
JWT vs Session: which is better?
Sessions store state server-side (requiring a database lookup per request). JWTs are stateless — all information is in the token, no server state needed. JWTs are better for distributed systems and microservices. Sessions are better when you need instant token revocation (JWTs can't be revoked before expiry without additional infrastructure).
Can a JWT be forged?
Without knowing the signing key, a valid JWT signature can't be forged (assuming a secure algorithm and strong key). However, the payload can be decoded by anyone — the signature guarantees integrity, not confidentiality.
Is the debugger free?
Yes — tool.tl's JWT debugger is completely free. All operations are local in your browser — your tokens never leave your device.