Handbooks / REST API Design / Chapter 3
Authentication and Authorization
7 pages · ~5 min✓ Reviewed
Builds on Resource Design. Next up: Versioning and Pagination.
API Keys, Sessions and Tokens
1. Authn vs Authz
| Authentication | Authorization | |
|---|---|---|
| Asks | Who are you? | What may you do? |
| Fails | 401 | 403 |
2. Three Credentials
- API key: static secret naming an app
- Header
X-API-Key: <key>orAuthorization: Bearer <key>, never the URL - Session: server stores state, cookie holds opaque ID; revoke = delete record
- Token: signed, self-contained, no server record; scales, hard to revoke before expiry
| API key | Session | Token | |
|---|---|---|---|
| Is | machine identity, no user | stateful, cookie-bound | stateless, carries claims |
| Life | long-lived | server decides | short-lived |
| Revoke | rotate | easy | hard |
Never
A key in the URL leaks into logs.
3. Interview Point
- 401 vs 403? 401 not authenticated; 403 authenticated but not allowed
- Sessions easier to revoke? Delete the server record; a JWT lives until
exp - API key over OAuth? Server-to-server calls with no user context
JWT Structure and Pitfalls
1. Structure and Claims
- header.payload.signature, three base64url parts
- Header holds
alg,typ; payload holds claims
| Claim | Means |
|---|---|
iss | issuer |
sub | subject |
aud | audience |
exp | expiry, Unix seconds |
iat | issued at |
nbf | not before |
2. Verify Every Request
- Check signature,
exp,iss,aud - Signed is not encrypted: payload is readable, so no secrets or PII
| HS256 | RS256 | |
|---|---|---|
| Key | one shared secret | private signs, public verifies |
3. Pitfalls
- Accepting
alg: none - Trusting the header
alginstead of pinning it - Algorithm confusion: RS256 key used as HS256 secret
- Long expiry with no revocation
- JWT in localStorage, where XSS reads it
4. Interview Point
- Readable but tamper-proof? Base64 is encoding; any edit breaks the signature.
- alg=none attack? Forged unsigned token; stop it by pinning the allowed alg.
- HS256 vs RS256? HS256 within one service; RS256 when others must verify.
- Revoke a JWT? Short expiry plus a denylist, or rotate keys.
OAuth 2.0 Flows and Scopes
1. What OAuth 2.0 Is
- Delegated authorization: limited access, no password shared
- Roles: resource owner, client, authorization server, resource server
2. Flows
- /authorizeuser consents
- Callbackreturns code
- POST /tokencode + code_verifier
- Access token
| Flow | Use | Status |
|---|---|---|
| Auth Code + PKCE | web, SPA, mobile | use |
| Client Credentials | machine; id + secret to /token | use |
| Implicit, Password | none | deprecated |
- Send
code_challenge= BASE64URL(SHA256(code_verifier)) up front - Add
code_challenge_method=S256; verifier goes in the exchange - Stolen code is useless; use for all public clients
3. Scopes and state
- Scopes limit a token, e.g.
read:orders,write:orders - Requested in
scope, approved by the user - Resource server enforces scopes on each call
stateparameter blocks CSRF on the redirect
4. Interview Point
- Why PKCE? Stolen code is useless without the verifier
- Backend job, no user? Client Credentials
- Scope? Limits the token; resource server enforces it
- Why drop Implicit? Token exposed in the redirect URL
Refresh Tokens and Token Lifecycle
1. Two Tokens
| Access | Refresh | |
|---|---|---|
| Life | 5-15 min | long-lived |
| Sent to | every API call | /token only |
| Request | bearer header | grant_type=refresh_token |
2. Rotation and Storage
- Refresh usedPOST /token
- New pairnew refresh token
- Old one deadinvalidated
- Old one reusedtheft: revoke family
- Store server-side or in an HttpOnly, Secure, SameSite cookie
- Never in
localStorageor logs
3. Revocation and Token Type
| Opaque | JWT | |
|---|---|---|
| Check | introspection call | verified locally |
| Revoke | at once | valid until exp |
Revoking
Delete the refresh token on the server. Access tokens live until exp unless you keep a denylist or use introspection, so keep them short.
4. Interview Point
- Why split? A leaked access token dies fast; the refresh token never rides on API calls
- Rotation? Each use issues a new refresh token; reuse of an old one revokes the family
- Storage? Refresh: server or HttpOnly cookie; access: memory, never
localStorage
HTTPS and Transport Security
1. HTTPS and the handshake
- HTTPS = HTTP over TLS: encryption, integrity, server authentication
- Without it, keys, cookies and tokens can be sniffed
- Cert checks: trusted CA signed it, domain matches, unexpired, not revoked
- Never disable verification, e.g.
verify=False
- Client hello
- Certificatefrom server
- ValidateCA chain + hostname
- Session keysymmetric
- Encrypted data
2. Cookie flags and HSTS
| Flag | Stops |
|---|---|
Secure | cookie sent over plain HTTP |
HttpOnly | JS reading it (XSS theft) |
SameSite=Lax/Strict | cross-site sends (CSRF) |
http
Set-Cookie: sid=abc; Secure; HttpOnly; SameSite=Lax
Strict-Transport-Security: max-age=31536000HSTS makes browsers use HTTPS only
- Also redirect HTTP to HTTPS
3. URLs and Interview Point
No keys in URLs
Query strings leak into logs, browser history and Referer headers. Use the Authorization header.
- TLS handshake achieves? Authenticated server, shared session key, encrypted traffic
- Secure, HttpOnly, SameSite stop? Plain-HTTP sends, JS theft, CSRF
- Key in query string? It leaks into logs, history, Referer
Auth Cheat Sheet
1. Pick the Mechanism
| Need | Use |
|---|---|
| Server-to-server identity | API key |
| First-party web app | Session cookie |
| APIs, SPAs, third parties | JWT or OAuth access token |
2. JWT and OAuth
- Pin alg, never trust the header
- Verify signature,
exp,iss,aud - Short-lived, no secrets in payload
| Client | Flow |
|---|---|
| User-facing | Auth Code + PKCE |
| Machine | Client Credentials |
| Never | Implicit, Password |
3. Tokens and Transport
- Access token about 15 minutes
- Refresh token rotated, stored HttpOnly
- Revoke on logout and on reuse detection
- Always HTTPS + HSTS
- Secrets in env vars or a vault, never git or URLs
- Leaked key: rotate immediately
4. Interview Point
- Login to API call? HTTPS, Auth Code + PKCE, short access token, API checks
exp,aud, scope - Leaked token first? Revoke it and its refresh family, then rotate keys
- Sessions or JWTs? Sessions for first-party web: easy revoke
Check yourself
An attacker edits the JWT payload from role=user to role=admin and keeps the old signature. A correct server does what?
- Rejects it with 401: the signature no longer matches the payload.
- The payload is readable by anyone, but changing it breaks the signature.
Refresh token rotation is on. An old refresh token is presented a second time. What happens?
- Treated as theft: the server revokes the whole token family.
- The real user and the attacker both have to log in again.
A valid token with only scope read:orders calls DELETE /orders/7. Which status, and who decides?
- 403: the caller is authenticated but not authorized.
- The resource server must enforce the scope on every call.