Lion Cipher Lab
Write a JWT/OIDC access-token validator from scratch — and break the naive ones
- Identity & Access Management
- Advanced
- ~60 min
- Free · no account required
Why it matters
A JSON Web Token (JWT) is how nearly every modern OAuth 2.0 / OpenID Connect system tells your API 'this request is from an authenticated user.' It is three base64url-encoded parts joined by dots — a header, a payload of claims, and a signature — and the ONLY thing standing between a real token and a forged one is whether you check that signature correctly. That check is where teams get owned. The classic disasters are not exotic: a verifier that decodes the payload but never verifies the signature; a verifier that trusts the token header's own `alg` field and so accepts `alg:none` (no…
What you'll learn
- reading a JWT's three parts (header.payload.signature) and knowing that base64url is encoding, not protection
- minting a real RS256 JWT from an RSA keypair standing in for an OpenID Connect identity provider
- seeing exactly why a verifier that decodes without checking the signature 'accepts' a forged token
- building a correct validator one earned check at a time: signature, then algorithm pinning, then claims
- the RS256->HS256 key-confusion attack — why treating the PUBLIC key as an HMAC secret forges a token, and why pinning alg=RS256 kills it
- rejecting alg:none, expired/not-yet-valid tokens (exp/nbf with leeway), and wrong iss/aud (cross-service replay)
- selecting the signing key by kid from a known key set, and rejecting unknown or path-traversal kid values
- the judgment call: build-your-own only to learn; in production pin the algorithm and use a maintained library (PyJWT/jose)
Steps in this lab
- What a JWT actually is (three parts, and only one protects you)
- Stand up a fake IdP and mint one valid RS256 token
- The WRONG way: a naive verifier that trusts the payload
- Check #1 — verify the RS256 signature (defeats forgery)
- Check #2 — PIN the algorithm (defeats alg:none and RS256->HS256 confusion)
- Check #3 — validate the claims: exp/nbf, iss, aud (defeats replay & stale tokens)
- Check #4 — select the key by kid from a known set (defeats unknown / path-traversal kid)
- Fire everything at BOTH validators — the scoreboard
- The judgment: build-your-own to LEARN, then use the library