Back to the map

Module 04 · API fundamentals · Lesson 13 of 15

JWT

A JSON Web Token is a signed set of claims any holder of the key can verify. Its three parts, the claims that matter, symmetric versus asymmetric signing, key rotation with JWKS, and the validation mistakes that have produced real breaches.

CoreMust-knowMid 11 min Updated Nov 2026

Why it matters

JWTs are the lingua franca of modern authentication: OAuth providers issue them, API gateways verify them, and services pass them downstream. They are also widely misused, because a token that "just works" when decoded hides the fact that verification is the whole point. Knowing what a JWT does and does not promise is what lets you use it in a design without creating the vulnerabilities that make the news.

The idea

A JSON Web Token is three base64url-encoded parts joined by dots: a header (algorithm and key id), a payload of claims (JSON facts about the subject), and a signature over the first two. Anyone can decode and read it; only a holder of the key can create a valid signature; anyone with the verification key can check it. It is signed, not encrypted: never put secrets in the payload.

Headeralg: RS256, kid: k1Payloadsub, iss, aud, exp, scopeSignaturesign(header.payload)covered by signaturebase64url(header).base64url(payload).base64url(signature)
Header, payload and signature. The signature covers the first two parts, so any change to the claims invalidates it.

Claims that matter

ClaimMeaningVerify
issIssuer: who signed itMust equal the issuer you trust
subSubject: the user or service idUse as the principal
audAudience: which API this token is forMust include this service, or a token for one API works on another
expExpiry (Unix time)Reject if past; keep lifetimes short
iat / nbfIssued at / not beforeReject tokens from the future or before validity
jtiUnique token idNeeded if you ever want to deny-list a token
scope / roles / tenantApplication claimsAuthorize on them; keep them small

Symmetric versus asymmetric signing

HS256 uses one shared secret to sign and verify. Simple, fast, and every verifier can also forge tokens, so it suits a single service, not a fleet. RS256 or ES256 use a private key to sign and a public key to verify. The issuer keeps the private key; every service verifies with the public key and cannot mint tokens. This is the right choice as soon as more than one party verifies.

Key rotation with JWKS

The issuer publishes its public keys at a well-known URL as a JWKS (JSON Web Key Set), each with a key id. Tokens name their key in the header's kid. Verifiers cache the key set and refresh it when they see an unknown kid. Rotation is then routine: publish a new key, start signing with it, keep the old one listed until all tokens signed with it have expired, then remove it.

Validation mistakes that became breaches

  1. 1

    Trusting the header's algorithm

    A token claiming alg: none or switching RS256 to HS256 (so the public key is used as an HMAC secret) has fooled libraries. Pin the expected algorithm in the verifier; never let the token choose.
  2. 2

    Decoding without verifying

    Many libraries offer a decode function that does not check the signature. Using it for authentication accepts any token anyone types.
  3. 3

    Ignoring aud and iss

    A valid token from your login provider intended for a different app is still a valid signature. Check that it was issued by the right party for this audience.
  4. 4

    Long lifetimes with no revocation

    A 30-day stateless token is a 30-day window for a stolen one. Keep access tokens to minutes and pair with refresh tokens (previous lesson).
  5. 5

    Secrets in claims

    The payload is readable by anyone. Put identifiers and permissions in it, never passwords, personal data or internal hostnames.

Size and where it travels

A JWT with a few claims is a few hundred bytes and rides in every request's Authorization: Bearer header. Stuffing it with roles, preferences and profile data makes every request heavier and the data stale the moment it changes. Keep the token to identity and coarse permissions; fetch the rest.

Trade-offs

JWTs let any service verify identity without a round trip and carry claims across service boundaries, which is exactly what a distributed system wants. They cost delayed revocation, a readable payload, header overhead on every request, and a verification routine that must be done correctly in every service. Asymmetric keys with JWKS add a small amount of infrastructure and remove the shared-secret risk.

In an interview

Be specific about verification, because that is where designs go wrong: "The identity provider issues RS256 JWTs with a fifteen-minute expiry. Services fetch the JWKS, verify the signature with the pinned algorithm, and check iss, aud and exp before trusting sub and scope. Refresh tokens are server-side so we can revoke." Said in one breath, it covers every item on the checklist.

Check yourself

A service verifies JWTs by reading the alg field from the token header and using that algorithm with its RS256 public key. An attacker sends a token with alg set to HS256, signed using the public key as the HMAC secret. What happens?

JWT · Backplane