Security & Authentication

JSON Web Tokens: Structure, Signing, and Common Pitfalls

Everything developers need to know about JWTs — the three-part structure, signing algorithms, token validation, and security pitfalls to avoid.

What Is a JWT?

A JSON Web Token (JWT) is a compact, URL-safe token format for transmitting claims between two parties. JWTs are widely used for authentication and authorization in web applications and APIs.

JWT Structure

A JWT has three parts separated by dots: header.payload.signature

Header

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

Specifies the signing algorithm (HS256, RS256, ES256, etc.).

Payload (Claims)

{
  "sub": "user-42",
  "name": "Alice",
  "iat": 1672531200,
  "exp": 1672534800
}

Standard claims: sub (subject), iss (issuer), exp (expiration), iat (issued at), aud (audience), nbf (not before), jti (unique ID).

Signature

HMACSHA256(
  base64UrlEncode(header) + '.' + base64UrlEncode(payload),
  secret
)

The signature ensures the token hasn't been tampered with.

Signing Algorithms

AlgorithmTypeKeyUse Case
HS256SymmetricShared secretSingle-service apps
RS256AsymmetricRSA key pairDistributed systems
ES256AsymmetricEC key pairModern systems (smaller keys)

HS256: Both parties share the same secret. Simple but the secret must be distributed to every service that validates tokens.

RS256/ES256: The issuer signs with a private key. Validators verify with the public key (available via JWKS endpoint). Better for microservices.

Validating a JWT

Always validate:

  • Signature — Verify using the correct key/algorithm
  • Expiration (exp) — Reject expired tokens
  • Issuer (iss) — Ensure it's from a trusted source
  • Audience (aud) — Ensure the token is intended for your service
  • Algorithm — Reject none and unexpected algorithms

Common Pitfalls

1. The `alg: none` Attack

Attackers set the algorithm to none, bypassing signature verification. Always enforce an explicit algorithm allowlist on the server.

2. Algorithm Confusion

If your server expects RS256 but an attacker sends HS256, the public key may be used as the HMAC secret. Explicitly check the algorithm.

3. Not Checking Expiration

A JWT without exp is valid forever. Always set and check expiration.

4. Storing Sensitive Data in the Payload

JWT payloads are Base64-encoded, not encrypted. Anyone can decode and read them. Never put passwords, SSNs, or secrets in a JWT.

5. No Revocation Mechanism

JWTs are stateless — you can't revoke them once issued. Mitigate with:

  • Short expiration times (15 minutes)
  • A token blacklist for logout
  • Refresh token rotation

Best Practice

Use short-lived access tokens (15 min) with refresh tokens (7 days). Use RS256/ES256 for distributed systems. Always validate all claims.

Related Protocols

Related Glossary Terms

More in Security & Authentication