Free & open · no paywall, ever

IntegrAuth Academy

Identity, security and practical AI — free, from zero. Byte-sized lessons, real diagrams, hands-on labs, zero fluff. Two programs, each with its own exam and certificate.

20 tracks 241 lessons 242 hands-on labs 230+ diagrams 100% free

English is hard? Your browser can translate this page into Tamil, Telugu, Kannada, Malayalam or Hindi. Tech words stay in English so you learn the real names.

How?
  • Chrome on phone: ⋮ menu → Translate
  • Chrome on computer: right-click → Translate to …
  • Edge: the translate icon in the address bar
Identity & API Security Track 3 · Token Security
0/166 lessons read
TOKEN SECURITY · LESSON 8

Validating a JWT — the key checks

A JWT arrives at your API's door. Before the API trusts one word, it must ask two questions. Is this token real? Is it meant for me? Your goal: list the checks an API must make, in order.

Key points
  • Decoding only reads a token. It does not prove anything.
  • First check the signature. Then check the claims.
  • Check iss, aud, exp and nbf every time.
  • Pin the algorithm and take keys only from your own trusted key set.

Decoding is not verifying

The first temptation is to decode the token, read the claims and move on. That is the trap. Decoding only unpacks the letters, and anyone can write a letter. Verifying proves that the issuer really sealed the token. So checking a JWT has two moves, in this order. First check the signature. Then check the claims. Skip the first, and every claim is made up by the attacker. New to tokens? See the tokens lesson.

Step one: verify the signature

The issuer makes the signature with its private key. You check it with the matching public key. You fetch that key from the issuer's JWKS (JSON Web Key Set). You pick the right key with the token header's kid (key ID). For where keys live and why you can trust them, see federation trust. A good signature means the claims are exactly what the issuer wrote. Only now are they worth reading.

Step two: check the claims

Each check is one quick question. Miss one and the door opens.

CheckThe questionReject when…
signatureDid the real issuer seal this, unchanged?The seal does not match the issuer's key.
iss (issuer)Did it come from the issuer I expect?iss is not exactly your expected value.
aud (audience)Is this token meant for this API?aud names a different service.
exp / nbfIs it inside its valid time window?Now is after exp, or before nbf (not before).

Teams often skip the aud check. Then a token made for another service can be replayed against yours. Every API should accept only tokens that carry its own name. This is also why token exchange makes a fresh token with a narrow audience. Also check the token type, so an ID token cannot pass as an access token. See ID tokens vs access tokens.

JWT arrives(untrusted)① SignatureJWKS · kid② ississuer ok?③ audfor THIS API?④ exp / nbfin the window?200 · trustedclaims believedforged: alg:noneaud: other-api✗ 401 — no real signature✗ 401 — audience mismatch
Figure — Four gates, in order. A real token passes every gate and gets a trusted 200. The alg:none forgery dies at the signature gate. A token made for another service dies at the audience gate. One weak gate is all an attacker needs.

Four famous traps

🚫 The "alg:none" trap

The header says alg: none, which claims no signature is needed. A careless library accepts it, so anyone can forge a token. Fix: never accept none.

🔀 Algorithm confusion

The attacker changes the header to HS256. A careless verifier then treats the issuer's public RSA key as a shared secret. Everyone knows that key, so anyone can sign. Fix: pin the exact algorithm you expect.

👀 Decode only

Reading the claims without checking the seal. The token "works", until an attacker sends handwritten claims. Always verify first.

🗝️ Rogue key pointer

A header such as jku, x5u or an embedded jwk points to a key the attacker chose. Fix: take keys only from your own pinned, trusted JWKS.

Think of it like…

A railway TTE checking your ticket. First they check that the ticket is genuine, not a photocopy. That is the signature. Then they read it: issued by the Railways (iss), for this train (aud), for today (exp). A paper that says "no stamp needed" is the alg:none trick.

Watch out

Use a well-kept library. Give it a short list of allowed algorithms, your exact iss and your own aud. Never write your own JWT crypto. For what the trusted claims should say, see the claims lesson.

Go deeper: the standards

The four traps come from the JWT best-practice guide, RFC 8725. A JWT access token should have typ: at+jwt in its header (RFC 9068). This stops someone from using an ID token as an access token.

🧪 Interactive lab — enable JavaScript to play with this one.

🧪 Try it free

Inspect a real JWT and grade its claims with ID Token Check. Then check the signing keys behind the seal with JWKS Check.