What is a JWT: Compact, Stateless Claims

JSON Web Token (JWT) is an open industry standard (RFC 7519) designed for securely transmitting assertions between parties as a compact JSON object. JWTs are overwhelmingly employed in modern cloud architectures, single-page applications, and microservices for stateless user authentication and fine-grained authorization.

The standout advantage of standard JWT architecture is that it is stateless. An API gateway or downstream microservice does not need to query a central session store (like Redis or PostgreSQL) on every inbound HTTP request. All pertinent contextual assertions (user ID, tenant, role permissions, expiration time) are contained within the token, and mathematical signatures guarantee integrity.

Critical Misconception: JWT is not encryption! Standard tokens are merely Base64Url encoded and signed. Anyone with access to the raw token string can view the payload contents in milliseconds. Never store passwords, payment card numbers, social security IDs, or secret API credentials in a JWT payload.

Anatomy of a JWT: Three Dot-Separated Segments

A valid JSON Web Token consists of three distinct components separated by periods: header.payload.signature

1. Header

Contains token metadata: the type of token (typically "JWT") and the cryptographic signing algorithm in use. Examples include symmetric algorithms like HS256 (HMAC with SHA-256) or asymmetric pairs like RS256 (RSA signature with public/private keys).

{
  "alg": "HS256",
  "typ": "JWT"
}
2. Payload (Claims)

Houses the actual claims—statements regarding the subject and contextual data. The specification groups claims into registered (reserved standard fields), public, and private custom claims.

{
  "sub": "user_98412",
  "name": "Alex Miller",
  "role": "editor",
  "iat": 1792929600,
  "exp": 1792933200
}
3. Signature

A cryptographic digest proving that neither the header nor payload was tampered with during transit. For HMAC-SHA256, it is calculated as:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret_key
)

Standard Registered Claims (RFC 7519)

To ensure cross-language interoperability between authentication providers and consumers, the specification reserves seven standard claims:

Claim Full Name Description and Example
iss Issuer Identifies the principal that issued the JWT (e.g. https://auth.example.com).
sub Subject The subject of the JWT (typically a unique user UUID or client ID).
aud Audience The recipients that the token is intended for. Servers must reject tokens if their identifier is absent.
exp Expiration Time Unix epoch timestamp (in seconds) identifying when the token expires and ceases to be valid.
nbf Not Before Identifies the time before which the JWT must not be accepted for processing.
iat Issued At Unix timestamp identifying the time at which the JWT was issued.
jti JWT ID A unique identifier for the token (UUID). Essential for token replay prevention and blacklisting.

5 Critical JWT Security Vulnerabilities

1. Blindly Trusting the "alg: none" Header

An infamous historical design flaw. When an authentication backend dynamically trusts the algorithm header supplied by the client, an attacker can submit a modified payload with {"alg": "none"} and an empty signature. Backend verifiers must strictly enforce expected signing algorithms in code: jwt.verify(token, secret, { algorithms: ['HS256'] }).

2. Algorithm Confusion Attacks (RS256 to HS256)

In systems utilizing asymmetric RS256, the server's public key is publicly accessible. Attackers change the token header algorithm to symmetric HS256 and sign the token using the server's public RSA key. If the backend fails to verify the expected algorithm type, it verifies the HMAC signature using the public key string, granting full unauthorized access.

3. Missing or Unvalidated Expiration (exp)

A token without an exp claim never expires. If an access token leaks through reverse proxy logs or compromised browser storage, attackers retain permanent persistence. Access tokens should have an active window of 5 to 15 minutes, coupled with secure refresh token rotation.

4. Leaking Production Tokens to Third-Party Online Decoders

Engineers frequently paste live production bearer tokens into random web-based decoders during debugging sessions. If that service logs payload contents or transmits tokens to third-party tracking scripts, credentials with administrative scope become compromised.

Always inspect tokens with zero-network, client-side tools. Our JWT Decoder executes entirely within your local browser sandbox via the native Web Crypto API: no tokens or secrets ever leave your machine.

5. Storing Sensitive Tokens in localStorage (XSS Exposure)

Any JavaScript executing on the page has full read access to window.localStorage. A single compromised supply-chain dependency or script injection vulnerability allows silent extraction of your bearer tokens. For browser applications, store session refresh credentials in HttpOnly, Secure cookies.

How to Decode JWT Payloads in Lightweight JavaScript

Because the header and payload are standard Base64Url strings, you can parse token claims in vanilla JavaScript without heavy dependencies:

function parseJwtPayload(token) {
  const base64Url = token.split('.')[1];
  if (!base64Url) throw new Error('Invalid JWT format');
  
  const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  const jsonPayload = decodeURIComponent(
    atob(base64)
      .split('')
      .map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
      .join('')
  );

  return JSON.parse(jsonPayload);
}

Related Digital Vault PRO Tools

🔐 Inspect headers, claims, and expiration timestamps directly in your browser without transmitting sensitive tokens across the network:
Open Secure JWT Decoder→

Frequently asked questions

Is a JWT token encrypted by default?

No. A standard JWT (technically a JWS or JSON Web Signature) is Base64Url encoded and digitally signed, but never encrypted. Any proxy server or client inspecting the token string can read the header and payload claims in plaintext. If confidentiality is mandatory, the JSON Web Encryption (JWE) specification must be used instead.

Can an attacker modify payload claims and send them back to the server?

An attacker can easily decode and edit the Base64Url payload, but the server will instantly reject the token upon verification. The digital signature is computed using a cryptographic hash over the header and payload using a secret key (HMAC) or private key (RSA/ECDSA). Changing even a single bit in the payload invalidates the signature.

What is the critical alg: "none" vulnerability in JWT?

The JWT specification defines a "none" algorithm for unsigned tokens. Vulnerable or poorly configured authentication libraries accepted tokens where attackers changed "alg" to "none" and removed the signature, granting administrative privileges without knowing the secret key. Modern authentication libraries must reject "alg": "none" by default.

Where is the safest place to store JWTs in a browser: localStorage or Cookies?

Storing sensitive tokens in localStorage leaves them completely vulnerable to Cross-Site Scripting (XSS) attacks, as any rogue third-party script can access them. The industry best practice for browser clients is storing refresh tokens in HttpOnly, Secure, SameSite=Strict cookies, while keeping short-lived access tokens solely in JavaScript application memory.

How do you revoke a stateless JWT before its exp claim expires?

Because JWTs are stateless, servers typically do not verify a session database on every request. Standard revocation strategies include: 1) Enforcing short access token lifetimes (5–15 minutes); 2) Maintaining a distributed Redis denylist of revoked jti token IDs; 3) Storing an incremental tokenVersion counter on the user account database record.