API › Module 4 › Lesson 3
Claims Hygiene
exp aud iss and humble payloads — validate on 127.0.0.1:8813.
Visual · jwt_claims_hygiene
Validate exp/aud/iss; minimal claims. 127.0.0.1:8813.
Opening
A verified signature on an expired token for the wrong audience is still a fail.
After verify, check time and audience: exp (expiry), nbf (not before), iss (issuer), aud (audience). Keep payloads minimal — roles are sensitive; secrets do not belong. Clock skew policies exist; infinite-lived lab tokens are a teaching smell outside a toy. Original Cyberlium. Practice claim checks on 127.0.0.1:8813. No stranger token collection. No phishing for id_tokens. Next: JWT Lab — Decode and Verify.
1. Time and audience are not optional spice
Reject expired tokens. Reject wrong aud if your API is not the intended recipient. Reject unexpected iss when you have a known issuer.
On YOUR lab, use an expired teaching token and record the deny. That is hygiene, not “JWT hacking the internet.”
Command guide
Try these commands — Time and audience are not optional spice
═══ TOOLS & WEBSITES ═══ Browse / read these (authorized learning only — stay in YOUR lab / program scope)
JWT claims — https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims jwt.io debugger — https://jwt.io/
═══ INSTALL ═══
Linux (Debian/Ubuntu):
Command — copy this
sudo apt install python3 sudo apt install jq
macOS:
Command — copy this
brew install python3 brew install jq
Windows: Download https://python.org/downloads/
Command — copy this
choco install jq
═══ LINUX / macOS ═══
Command — copy this
python3 - <<'PY'
import base64,json,time
claims={'sub':'lab','exp':int(time.time())+300,'aud':'127.0.0.1:8813'}
b=base64.urlsafe_b64encode(json.dumps(claims,separators=(',',':')).encode()).rstrip(b'=').decode()
print('payload b64url', b); print('Always verify signature + exp + aud on YOUR lab')
PYCommand — copy this
curl -sS http://127.0.0.1:8813/.well-known/jwks.json 2>/dev/null | jq '.keys[0].kid // "no jwks yet"'
Primary tools to practice this lesson: python3, jq. Reference sites: JWT claims (https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-token-claims); jwt.io debugger (https://jwt.io/). Run every command in the box — install first, then the usage lines — only on YOUR lab / program scope.
2. Minimal claims, no secrets in payload
sub and a role may be enough. Do not stuff passwords, refresh tokens, or PANs into JWT payloads. Readable means exfiltrated if the token leaks.
Prefer opaque server sessions when you need immediate revoke; JWT revoke needs denylist/short TTL patterns — name the tradeoff in notes.
3. Ethics
Do not scrape live JWTs from browser storage on shared PCs that are not yours. Lab tokens only.
Ship a checklist: verify → exp → aud/iss → then authorize.
4. What you ship: a claims checklist and an expired-token deny
Checklist verify→exp→aud/iss. Expired lab token rejected. Minimal-claims rule. Dest 127.0.0.1:8813. No stranger token scrapes.
5. What you record before the next lesson
Date. Checklist. Expired-token status. File t13-m04-l03-claims-hygiene.txt chmod 600.
6. Wrong vs right: stranger APIs vs literacy on systems you own
Worked failure — same API word, opposite target. Right never needs a live shop or classmate token.
Wrong
Infinite prod JWTs with role=admin in plaintext forever. Put passwords in claims. Replay random stolen JWTs.
Right
Checklist + lab deny. Next: JWT Lab — Decode and Verify.
Mission: validate claims after verify
1) / STOP if router. 2) Write claims checklist. 3) Show expired lab JWT rejected on 127.0.0.1:8813. Never replay stranger tokens.
Stuck? Ask Cyberlium AI Mentor
Ask Mentor how your framework validates aud — not how to extend exp on a production token.
Knowledge Check
APPLY: Signature verifies but exp is in the past. You:
Multiple choice
Knowledge Check
APPLY: True or False: Passwords belong in JWT payloads for convenience.
True or False
Knowledge Check
APPLY: Wrong aud for your API means:
Multiple choice