Skip to content
Expensico

What Is a JWT? Structure, Claims and Common Mistakes

By Antuparthi Manoha Malik PaulPublished 3 October 20267 min read

How JSON Web Tokens are built, what the header, payload and signature do, and the security mistakes to avoid when using them.

JSON Web Tokens (JWTs) are everywhere in modern web apps: you get one when you log in, and your browser sends it with each request. They're simple, but easy to misuse.

Structure

A JWT is three Base64URL-encoded parts separated by dots:

header.payload.signature
  • Header — metadata, mainly the signing algorithm, e.g. {"alg":"HS256","typ":"JWT"}.
  • Payload — the claims: statements about the user and the token.
  • Signature — computed over the header and payload with a secret or private key.

Standard claims

issIssuer — who created the token
subSubject — usually the user ID
audAudience — which service the token is for
expExpiry time (seconds since 1 January 1970, UTC)
nbfNot valid before this time
iatIssued at
jtiUnique token ID, useful for revocation

Signed, not encrypted

The payload of a normal JWT is only encoded. Anyone holding the token can decode it — try it in the JWT decoder. The signature prevents tampering, not reading. Never put passwords, personal identifiers you wouldn't show the user, or secrets in a JWT payload. (Encrypted JWTs, called JWE, exist but are much less common.)

HS256 vs RS256

  • HS256 uses one shared secret to sign and verify. Simple, but every service that verifies tokens can also create them.
  • RS256/ES256 sign with a private key and verify with a public key, so services can check tokens without being able to forge them. Public keys are often published at a JWKS URL.

Common mistakes

  • Trusting the token's own alg header. Servers must enforce the expected algorithm; accepting alg: none or switching RS256 to HS256 has led to real vulnerabilities.
  • Not checking exp, aud and iss. A valid signature isn't enough.
  • Long-lived access tokens. JWTs are hard to revoke. Keep access tokens short-lived (minutes) and use refresh tokens.
  • Weak HMAC secrets. Use long random secrets; short ones can be brute-forced offline from any captured token.
  • Pasting production tokens into online tools that log them. Use a decoder that runs locally in your browser.

Where to store tokens in a browser

HttpOnly, Secure, SameSite cookies keep tokens out of reach of JavaScript, which limits damage from cross-site scripting, but require CSRF protection. Storing tokens in localStorage is simpler but exposes them to any script running on the page. Whichever you choose, a strict Content Security Policy and short token lifetimes help.

Related tools: Base64 decoder and the Unix timestamp converter for reading exp and iat.