How It Works: AuthN/AuthZ — Sessions, JWT, 2FA, OAuth2, CSRF

 

Updated: 2025-08-24

Summary

Authentication proves identity; authorization determines permissions. For browsers, default to server sessions + secure cookies and CSRF defenses. For APIs/mobile, use short‑lived JWT access tokens with refresh tokens. Layer 2FA, strong secrets management, and defense‑in‑depth on every hop.

Sessions (Browser)

- Server stores session state (Redis). Client holds opaque cookie.
- Set cookie flags: HttpOnly; Secure; SameSite=Lax (or Strict for sensitive flows).
- Rotate session on login and privilege changes; short TTL + sliding refresh.
- CSRF protection: double‑submit token or SameSite plus custom header.

# Example Set-Cookie (HTTP response)
Set-Cookie: sid=abc123; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=7200

# CSRF: double submit (store token in session, send in header)
X-CSRF-Token: <random-128-bit>
# Server checks header value matches token in session

JWT (APIs / Mobile)

- Self‑contained claims signed with strong alg (RS256/EdDSA).
- Short access token TTL (5–15 min) + refresh token (days) bound to device.
- Validate: signature, issuer, audience, expiry, not‑before.
- Rotate signing keys; publish JWKs; support kid for key lookup.
- Revoke on risk events via allow/deny lists or rotating `jti` with server list.

// Go: verify RS256 JWT (using github.com/golang-jwt/jwt/v5)
func Verify(tokenStr string, jwkSet *jose.JSONWebKeySet) (*jwt.Token, error) {
  keyfunc := func(t *jwt.Token) (any, error) {
    kid, _ := t.Header["kid"].(string)
    for _, k := range jwkSet.Keys {
      if k.KeyID == kid { return k.Key, nil }
    }
    return nil, errors.New("unknown kid")
  }
  return jwt.Parse(tokenStr, keyfunc, jwt.WithAudience("api"), jwt.WithIssuer("https://auth.example.com"))
}

OAuth2/OIDC (Login with Google/Apple/etc.)

- Use Authorization Code + PKCE for public clients.
- Store minimal profile; map provider subject → internal user ID.
- Keep redirect URIs strict; validate state to prevent CSRF.
- Refresh/rotate tokens on schedule; handle provider outages gracefully.

2FA & Trusted Devices

- Deliver OTP via app/email; rate‑limit attempts.
- “Remember device” = signed, HttpOnly cookie + device record server‑side.
- Expire trust on password change, device removal, or risk signals.
- Backup codes printed once; store hashed.

RBAC and Secure API Design

- Enforce authorization at the edge and in each service.
- Prefer role + fine‑grained permissions/attributes (ABAC) for sensitive ops.
- Deny by default; minimal scopes; never trust client‑supplied roles.

Security Headers & HTTPS

Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
Referrer-Policy: no-referrer
X-Frame-Options: DENY
X-Content-Type-Options: nosniff

Secrets Management

- Store secrets in vault/KMS; mount via short‑lived tokens.
- Rotate keys regularly; audit usage; avoid secrets in images or logs.
- Pin dependencies; verify signatures; lock down CI/CD secrets.

Auditability

- Log auth flows with request_id and user_id (no passwords/tokens).
- Record 2FA events, scope grants, and admin changes.
- Retain logs per policy; encrypt at rest and in transit.

Pitfalls

- Long‑lived JWTs with broad scopes.
- Missing CSRF protections on cookie‑based APIs.
- Overloading refresh tokens (use rotation and reuse‑detection).
- Not checking `aud`/`iss` → token confusion.

Taylor Swift

“I keep my side of the street clean.”


Comments

Popular posts from this blog

Learning to Automate My Side Projects with SWE-agent + GitLab

Ship-Ready Web Essentials: Search, Sitemap, Metadata & Icons (SvelteKit)

Kubernetes Secrets Management — SOPS + age (GitOps‑friendly)