HTTP Cheatsheet
Authentication
Use this HTTP reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Basic auth
curl -u alice:s3cret https://api.example.com/v1/me # equivalent to printf 'alice:s3cret' | base64 # YWxpY2U6czNjcmV0 curl -H 'Authorization: Basic YWxpY2U6czNjcmV0' https://api.example.com/v1/me
Base64 is encoding, not hashing, so credentials travel in effectively plaintext. It is acceptable only over TLS, for machine-to-machine calls, or behind an internal proxy. Browsers cache the credentials for the realm and there is no clean logout, which is the practical reason it disappeared from user-facing apps.
Bearer tokens: opaque vs JWT
| Opaque token | JWT | |
|---|---|---|
| Content | a random identifier | signed, self-describing claims |
| Validation | a lookup, DB or cache | verify a signature locally |
| Revocation | delete the row, instant | hard, needs a denylist or short TTLs |
| Size | small, 32-64 bytes | 500 bytes to several KB |
| Readable by the client | no | yes, base64 is not encryption |
| Statelessness | no | yes, which is the whole point |
| Introspection | POST /introspect (RFC 7662) | decode locally |
JWT structure, three base64url parts joined by dots
eyJhbGciOiJSUzI1NiIsImtpZCI6ImsxIn0 header {"alg":"RS256","kid":"k1"}
.eyJzdWIiOiI4ODE0IiwiZXhwIjoxNzg5fQ payload {"sub":"8814","exp":1789...}
.QhTsx9K7... signature over header.payload| Claim | Meaning | Verify it |
|---|---|---|
iss | issuer | matches the expected issuer exactly |
sub | subject, the user id | — |
aud | audience | your API is in the list |
exp | expiry, epoch seconds | now < exp, allow small clock skew |
nbf | not before | now ≥ nbf |
iat | issued at | — |
jti | unique token id | for replay detection and denylists |
JWT validation rules that get skipped and cause real breaches: never trust the
alg in the header (pin the expected algorithm, or alg: none and
HS256-with-the-public-key attacks apply), always verify the signature before
reading any claim, always check exp and aud, and resolve kid against a JWKS
you fetched from the issuer over TLS.
Never put secrets in a JWT payload. Anyone holding the token can read it.
Sessions vs tokens
| Server session cookie | Bearer token in JS | |
|---|---|---|
| Storage | server side, cookie holds only an id | localStorage, memory, or a cookie |
| XSS exposure | protected by HttpOnly | readable by any injected script |
| CSRF exposure | yes, needs SameSite plus a token | no, if sent in a header |
| Revocation | delete the session, instant | needs short TTLs or a denylist |
| Cross-domain APIs | awkward, CORS plus SameSite=None | straightforward |
| Scaling | shared store, or sticky sessions | stateless |
The pattern that gets the best of both for a browser app: keep the access token in
memory only, keep the refresh token in an HttpOnly, Secure,
SameSite=Strict cookie scoped to the refresh endpoint. Never put a long-lived
token in localStorage, because one XSS is total account compromise with no
expiry.
API keys, HMAC signing, and mTLS
# API key, simplest machine credential. header, never a query string curl -H 'Authorization: Bearer sk_live_...' https://api.example.com/v1/orders curl -H 'X-API-Key: sk_live_...' https://api.example.com/v1/orders # HMAC request signing, resists replay and proves body integrity ts=$(date +%s) body='{"sku":"HU-100"}' sig=$(printf '%s\n%s\n%s' "$ts" "POST /v1/orders" "$body" \ | openssl dgst -sha256 -hmac "$SECRET" -binary | base64) curl -X POST https://api.example.com/v1/orders \ -H "X-Timestamp: $ts" -H "X-Signature: $sig" -d "$body" # mutual TLS, the client proves itself with a certificate curl --cert client.pem --key client.key https://api.example.com/v1/orders
Webhook receivers should verify an HMAC signature over the raw body, compare with a constant-time comparison, and reject timestamps outside a few minutes to stop replay.
Hardening checklist and failure modes
| Practice | Why |
|---|---|
| TLS everywhere, HSTS on | every scheme above leaks in plaintext |
| Short access token TTL (5-15 min) | limits the blast radius of a leak |
| Rotate refresh tokens, detect reuse | a replayed refresh token means theft |
HttpOnly, Secure, SameSite on session cookies | XSS and CSRF |
| Rotate the session id on login and privilege change | session fixation |
Rate limit auth endpoints, return 429 with Retry-After | credential stuffing |
| Constant-time comparison for tokens and signatures | timing side channels |
| Hash passwords with argon2id or bcrypt | never store or encrypt them |
Keep tokens out of URLs, logs, and Referer | query strings leak everywhere |
| Scope tokens narrowly, one audience each | a stolen token should not be universal |
# what does the server actually challenge with? curl -sI https://api.example.com/v1/me | grep -i www-authenticate # decode a JWT payload locally, no verification, inspection only cut -d. -f2 <<<"$JWT" | tr '_-' '/+' | base64 -d 2>/dev/null | python3 -m json.tool