Lesson 240·M23 Backend & Distributed Systems
JWT
OpenLearning Objectives
By the end of this lesson you should be able to:
- Explain JWT: the header, the payload, the signature (L240)
- Explain the claims: identity, expiry, audience (L240)
- Explain the verification: signature, expiry, audience (L240)
- Explain the stateless value: no server lookup (L240)
- Explain the trade: revocation and the token's life (L240)
One-Line Definition
JWT is the self-contained bearer credential — the header, the payload (the claims: identity, expiry, audience), and the signature (L240) — verified by the signature with no server lookup (L240), the stateless token behind the access tokens (L239) and the ID tokens (L239) of every modern API (L240).
The one-sentence interview answer: "JWT is the self-contained token (L240). Three parts: the header — the algorithm; the payload — the claims: the subject (who), the expiry (when it dies), the audience (who it's for) (L240); and the signature — the header and the payload signed with the server's secret or key (L240). The verification: verify the signature (L240) — the token wasn't forged; check the expiry (L240) — it isn't dead; check the audience (L240) — it's for this API. The value: the token is self-contained (L240) — the identity and the expiry ride in the token, so the verification needs no server lookup (L240): stateless, fast (L151). The trade: the token can't be revoked until it expires (L240) — so the expiries are short (L240) and the refresh token (L239) renews them (L239). Every modern API's access token (L239) and ID token (L239) is a JWT (L240)."
Mental Model
Think of the JWT as a stamped, signed passport. The passport (the token, L240) carries the traveler's identity (the claims, L240), the issue and expiry dates (L240), and the destination (the audience, L240). The border guard (the API's verification, L240) checks: the seal is authentic (the signature, L240), the passport isn't expired (the expiry, L240), and the destination matches (the audience, L240). The guard doesn't call the home country (no server lookup, L240) — the passport is self-contained (L240). The trade: a stolen passport works until it expires (L240) — so passports are short-lived (L240) and renewed (the refresh, L239).
the passport (the JWT, L240)
┌────────────────────────────────────────────────────────┐
│ header — the algorithm (L240) │
│ payload — identity · expiry · audience (L240) │
│ signature — the seal (L240) │
└────────────────────────────────────────────────────────┘
checked at the border (L240): seal, expiry, destination
The mental model is the stamped passport: self-contained, verified by its seal, short-lived (L240).
Visual Flow — The Verification Path
a request with a token arrives (L240)
│
▼
┌──────────────────────────────────────────────────────────┐
│ 1 · THE SIGNATURE (L240) │
│ is the seal authentic? — verify with the key (L240) │
│ forged → 401 (L234) │
└──────────────────┬───────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────┐
│ 2 · THE EXPIRY (L240) │
│ is the token dead? — the exp claim (L240) │
│ expired → 401 (L234) │
└──────────────────┬───────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────┐
│ 3 · THE AUDIENCE (L240) │
│ is it for this API? — the aud claim (L240) │
│ wrong → 401 (L234) │
└──────────────────┬───────────────────────────────────────┘
▼
the claims are trusted — the token is the identity (L240)
The flow is the verification: signature → expiry → audience — the border guard's three checks (L240).
How It Works — The Parts, the Claims, the Verification
- The parts (L240). The header — the signing algorithm (L240); the payload — the claims (L240); the signature — the header and the payload signed with the secret or the private key (L240).
- The claims (L240). The token's statements: the subject (who — the user or the service, L237), the expiry (when it dies, L240), the audience (who it's for, L240), the issuer (who signed it, L240), and the scopes (what it may do, L238).
- The verification (L240). The API verifies: the signature (L240) — not forged; the expiry (L240) — not dead; the audience (L240) — for this API; and the scopes (L238) — for this operation. Then the claims are trusted (L240).
- The stateless value (L240). The token is self-contained (L240): the identity and the expiry ride in the token (L240) — the verification needs no server lookup (L240): stateless and fast (L151).
- The trade (L240). A stolen token works until the expiry (L240) — so the expiries are short (L240), the refresh token (L239) renews them (L239), and the revocation happens at the refresh (L239).
Note
The verification is the trust — decoding is not verifying (L240). The demo mistake: decode the token (base64 — readable by anyone) and trust the payload (L240). The senior path: verify the signature (L240) — the token was signed by the trusted key (L240) — then check the expiry (L240) and the audience (L240). A decoded-but-unverified token is a forged token accepted (L240). The verification path is the trust boundary (L240) — in front of every API (L233).
Real Project Usage
- The access tokens (L239). The OAuth access token (L239) is a JWT (L240) — the scopes (L238) and the expiry (L240) in the claims (L240).
- The ID tokens (L239). The OIDC ID token (L239) is a JWT (L240) — the identity claims (L240), verified by the signature (L240).
- The service tokens (L237). The service-to-service tokens (L237) are JWTs (L240) — the service identity (L237) and the short expiry (L240).
- The sessions (L237). The app's own session token (L237) as a JWT (L240) — stateless sessions (L240).
- Anything with a token (L260). The JWT (L240) is the standard bearer (L240) — the verification path in front of every API (L260).
The through-line: JWT is the token's standard — the signed, self-contained claims behind the access tokens and the ID tokens (L240).
Interview Explanation
Say it in four moves:
- The parts. "Header, payload (the claims), signature (L240)."
- The verification. "Signature (L240) → expiry (L240) → audience (L240)."
- The value. "Self-contained — no server lookup (L240), stateless and fast (L151)."
- The trade. "Can't revoke until the expiry (L240) — short expiries (L240), refreshed (L239)."
Senior-Level Insights
- Verifying is the trust (L240). The senior answer verifies the signature (L240) — the decode-without-verify is the forgery accepted (L240).
- The claims are the contract (L240). The subject (L237), the expiry (L240), the audience (L240), the scopes (L238) — the token's claims are the authorization's input (L238).
- The stateless value is the scale (L240). No server lookup (L240) — the verification scales horizontally (L252) with no shared session store (L240).
- The short expiry is the security (L240). The stolen token's life is the expiry (L240) — short expiries (L240), the refresh (L239) as the renewal (L239).
- The algorithm choice is the hygiene (L240). The signing algorithm (L240) — the strong algorithms (L240), never the "none" (L240).
Common Mistakes
- Decode without verifying (L240). The payload trusted unverified (L240) — the forged token accepted (L240).
- The expiry unchecked (L240). The dead token accepted (L240) — the exp claim skipped (L240).
- The audience unchecked (L240). The token for another API accepted (L240) — the aud claim skipped (L240).
- The long expiries (L240). The stolen token's life is months (L240) — the short expiry (L240) and the refresh (L239) missing.
- The weak algorithm (L240). The "none" or the weak hash (L240) — the signature bypassed (L240).
- The secret in the client (L275). The signing secret exposed (L172) — the signature forgeable (L240).
Best Practices
- Verify, don't just decode (L240) — the signature first (L240).
- Check the expiry (L240) — the exp claim (L240).
- Check the audience (L240) — the aud claim (L240).
- Keep the expiries short (L240) — with the refresh (L239).
- Use the strong algorithms (L240) — and the server-side secret (L275).
- Include the scopes (L238) — the token's fine print (L240).
Interview Questions
Q: What is a JWT?
A: The self-contained bearer token (L240): the header — the signing algorithm; the payload — the claims: the subject (who), the expiry, the audience (L240); and the signature — the header and the payload signed with the key (L240). The verification: the signature (L240), the expiry (L240), the audience (L240). The value: self-contained (L240) — the identity rides in the token, no server lookup (L240).
Q: How do you verify a JWT?
A: The verification path (L240): the signature — is it signed by the trusted key (L240)? The expiry — is it alive (L240)? The audience — is it for this API (L240)? And the scopes — may it do this (L238)? Decoding is not verifying (L240) — the payload is readable by anyone, so the signature is the trust (L240).
Q: Why are JWTs stateless?
A: Because the token is self-contained (L240). The identity and the expiry ride in the claims (L240) — the verification needs no server-side session lookup (L240). The API verifies the signature and trusts the claims (L240) — stateless and horizontally scalable (L252). The session store (L237) is unnecessary (L240).
Q: What's the trade-off?
A: The revocation (L240). A stateless token can't be revoked until it expires (L240) — a stolen token works until the expiry (L240). So the senior design keeps the expiries short (L240) and uses the refresh token (L239) for the renewal (L239): the access token dies quickly, and the revocation happens at the refresh (L239). The short expiry is the security (L240).
Follow-Up Questions
- What are the three parts (L240)?
- What's the verification path (L240)?
- Why are JWTs stateless (L240)?
- What's the revocation trade (L240)?
- How do the scopes ride in the token (L238)?
Comparison Table — Opaque vs JWT
| Opaque token (L237) | JWT (this lesson) | |
|---|---|---|
| Content | a random ID | the claims (L240) |
| Verification | a server lookup (L237) | the signature (L240) |
| State (L240) | server-held | self-contained (L240) |
| Revocation (L240) | immediate | at the expiry (L240) |
| Scale (L252) | the shared store | stateless (L240) |
| The fit (L240) | revocable sessions | short-lived, scalable |
The senior read: the columns are the trade — the revocable lookup vs the stateless signature (L240).
Code Example — The Verification Path
// JWT: the verification path — signature, expiry, audience (L240).
export async function verifyToken(token) {
// 1 · THE SIGNATURE (L240) — the seal: signed by the trusted key?
const payload = verifyJwt(token, { // the signature (L240)
algorithms: ['RS256'], // the strong algorithms (L240)
});
// 2 · THE EXPIRY (L240) — is it alive? (the library checks `exp`).
if (Date.now() / 1000 > payload.exp) {
throw new TokenExpiredError(); // the dead token (L240)
}
// 3 · THE AUDIENCE (L240) — is it for THIS API?
if (!payload.aud.includes(API_AUDIENCE)) {
throw new TokenAudienceError(); // the wrong destination (L240)
}
// 4 · THE SCOPES (L238) — may it do this operation?
if (!payload.scopes?.includes(requiredScope)) {
throw new TokenScopeError(); // the fine print (L238)
}
return payload; // the claims are trusted (L240)
}
// THE GATEWAY (L236) — the verification in front of every API (L233).
const claims = await verifyToken(req.headers.authorization?.slice(7));
if (!claims) return error(401, 'invalid token'); // L234
What the reader must SEE — the border guard's checks:
verifyJwt(algorithms) → the seal (L240)
payload.exp → the expiry (L240)
payload.aud → the destination (L240)
payload.scopes → the fine print (L238)
Verify, don't just decode — the claims are trusted only after.
Tip
The trio that defines the trust: verifyJwt(token) (the seal, L240), payload.exp (the life, L240), and payload.aud (the destination, L240). The stamped passport — seal, dates, destination — verified at the border, no phone call home (L240).
Performance Notes
- The verification is stateless and fast (L151). The signature (L240) — microseconds, no lookup (L240).
- The public-key verification scales (L252). The RS256 public key (L240) — any instance verifies (L252), no shared state (L240).
- The short expiry is the security/latency trade (L151). The short expiries (L240) mean more refreshes (L239) — the trade between the stolen token's life and the refresh's cost (L240).
- The token size is the payload (L151). The claims (L240) ride in every request (L240) — keep the claims lean (L240).
Debugging Scenarios
| Symptom | Likely cause | First thing to check |
|---|---|---|
| Forged tokens accepted | Decode, no verify (L240) | The signature check (L240) |
| Dead tokens accepted | The expiry unchecked (L240) | The exp claim (L240) |
| Cross-API tokens | The audience unchecked (L240) | The aud claim (L240) |
| Stolen tokens live too long | The long expiries (L240) | The short expiry + refresh (L239) |
| The secret leaked | In the client (L275) | Server-side (L172) |
Quick Revision Notes
- JWT = the self-contained bearer (L240): header, payload, signature.
- The claims: subject, expiry, audience, scopes (L240, L238).
- The verification: signature → expiry → audience (L240).
- The value: stateless — no lookup (L240).
- The trade: no revocation until the expiry (L240) — short expiries (L240), refreshed (L239).
- The rule: verify, don't just decode (L240).
Cheat Sheet
JWT = the self-contained bearer — the stamped passport
THE PARTS (L240)
header the signing algorithm (L240)
payload the claims: subject (who, L237) · exp (when it dies)
· aud (who it's for) · scopes (what it may do, L238)
signature the header + payload, signed (L240)
THE VERIFICATION (L240)
signature → not forged (L240)
expiry → not dead (L240)
audience → for this API (L240)
scopes → may it do this (L238)
DECODING IS NOT VERIFYING (L240) — the payload is public
THE VALUE (L240)
self-contained — the identity rides in the token (L240)
no server lookup (L240) — stateless, fast (L151), scalable (L252)
THE TRADE (L240)
no revocation until the expiry (L240)
short expiries (L240) + the refresh token (L239)
the short expiry is the security (L240)
INTERVIEW, 4 MOVES
1 parts "header, payload, signature (L240)"
2 verify "signature, expiry, audience (L240)"
3 value "stateless — no lookup (L240)"
4 trade "short expiries + refresh (L240, L239)"Key Takeaways
Recap
- JWT is the self-contained bearer credential (L240): the header, the payload (the claims), and the signature (L240)
- The verification path (L240): the signature (not forged, L240), the expiry (not dead, L240), the audience (for this API, L240), and the scopes (may it do this, L238)
- Decoding is not verifying (L240) — the payload is readable by anyone, so the signature is the trust (L240)
- The stateless value (L240): the identity and the expiry ride in the token (L240) — no server lookup, fast (L151) and horizontally scalable (L252)
- The trade is the revocation (L240): a stolen token works until the expiry (L240) — so the expiries are short (L240), with the refresh token (L239) as the renewal (L239)
- Every modern API's access token (L239) and ID token (L239) is a JWT (L240) — the standard bearer in front of every API (L260)
Check your understanding
Answer each one out loud. Then rate yourself honestly.
0/8What are the three parts of a JWT (L240)?
What's the verification path (L240)?
Why is decoding not verifying (L240)?
What makes JWT stateless (L240)?
What's the revocation trade (L240)?
What are the claims (L240)?
Why the short expiries (L240)?
Where do the scopes ride (L238)?
A Closing Note — The Stamped Passport
You now hold the token's standard: the signed, self-contained claims; the verification path — seal, dates, destination; and the short-expiry trade with its refresh. Every token now passes the border guard's checks (L240).
Next: the policy behind the scopes — RBAC & fine-grained access (L241), roles, permissions, and per-resource checks.