All ArticlesSecurity & Auth

Understanding JSON Web Tokens (JWT): Debugging Payload Structure & Common Pitfalls

DevStackTools Security
2026-02-01
8 min read

Try the Interactive Tool

Test and validate client-side with zero data uploads.

Open JWT Decoder

JSON Web Tokens (JWT), defined by **RFC 7519**, are an open standard for securely transmitting information between client applications and API servers as a compact, self-contained JSON object. They serve as the foundation for modern stateless authentication in microservices and OAuth 2.0 / OpenID Connect flows.

In this guide, we break down the anatomical structure of a JWT, explain public vs. private claims, and review critical security vulnerabilities developers encounter when implementing JWT verification.


1. The Anatomy of a JWT

A JWT is a single string composed of three distinct parts separated by dots ("."):

code
[Header].[Payload].[Signature]

An example encoded token:

code
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Part 1: Header

The header contains metadata regarding the token type and the hashing algorithm used to produce the signature (e.g., HS256 or RS256).

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

Part 2: Payload (Claims)

The payload contains the statement claims regarding the user entity and additional metadata. Claims fall into three categories:

1. **Registered Claims:** Pre-defined standardized names:

* "iss" (Issuer): Who issued the token.

* "exp" (Expiration Time): Unix timestamp after which the token is invalid.

* "sub" (Subject): Unique user ID or entity identifier.

* "iat" (Issued At): Unix timestamp when the token was created.

2. **Public Claims:** Custom claims registered in the IANA JSON Web Token Registry or defined with collision-resistant names (e.g., URLs).

3. **Private Claims:** Bespoke custom fields agreed upon by system authors (e.g., "role": "admin").

json
{
  "sub": "1234567890",
  "name": "Alice",
  "role": "system-administrator",
  "iat": 1516239022,
  "exp": 17516239022
}

Part 3: Signature

The signature is created by hashing the Base64URL-encoded header, the Base64URL-encoded payload, and a secret key (for symmetric algorithms) or private key (for asymmetric algorithms):

code
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secretKey
)

The server checks this signature upon receiving a request to ensure that the client or an attacker has not tampered with the header or payload contents.


2. Critical Vulnerabilities & How to Avoid Them

Vulnerability 1: The "alg: none" Exploit

Early JWT libraries allowed tokens to specify "alg": "none". Attackers could alter payload values (such as changing "role": "user" to "role": "admin"), delete the signature part, set alg to none, and submit the token to naive backends.

**Prevention:** Hardcode allowable verification algorithms in server-side authorization middleware. Never dynamically accept the algorithm specified in the unverified client header.

Vulnerability 2: Key Confusion Attack (HS256 vs RS256)

If your server expects an asymmetric RSA public key (RS256) but accepts HS256 tokens, an attacker can obtain your public key (often exposed via "/.well-known/jwks.json") and sign a malicious token using the public key as an HMAC secret key!

**Prevention:** Explicitly enforce algorithm checks on your backend verifier:

javascript
// Good: Enforce specific expected algorithm
jwt.verify(token, publicKey, { algorithms: ['RS256'] });

3. Best Practices for JWT Storage in Web Apps

| Storage Mechanism | XSS Vulnerability | CSRF Vulnerability | Recommendation |

| :--- | :--- | :--- | :--- |

| **LocalStorage / SessionStorage** | High | None | Avoid storing sensitive auth tokens here |

| **HTTP-Only, Secure Cookie** | None | Low (if SameSite set) | **Best Practice** for browser web apps |

Storing JWTs in LocalStorage exposes them to malicious third-party scripts loaded via XSS. Always store authentication session tokens in HttpOnly, Secure, SameSite=Strict cookies.


Inspect JWT Tokens Securely

Pasting proprietary authorization headers into public third-party decoding websites poses severe security risk. Decode and inspect JWT headers, expiration timestamps, and payload attributes client-side using our private [JWT Decoder](/encoding/jwt-decoder).

Found this guide helpful?

Explore our 50+ privacy-first developer utility tools.

Explore Tools