Lesson 3 of 8 · 50 min

AuthN/Z: sessions, tokens, RBAC, service identity

Sessions vs JWT, OAuth altitude, RBAC and object-level authz, service-to-service identity, API keys, and agent tool authorization.

Lesson 3 · Auth

Sessions vs JWT, RBAC, service-to-service auth

Auth bugs are data breaches with extra steps

Authentication answers who; authorization answers what they may do. LLM products amplify risk: prompts may contain secrets, tools may exfiltrate, and service accounts often have god-mode provider keys. This lesson covers session cookies vs bearer JWTs, RBAC/ABAC instincts, and machine identity — the parts interviewers probe after “we use Auth0.”
Never conflate “logged in” with “allowed.” A valid session on tenant A must not read tenant B’s runs. Broken object-level authorization (BOLA/IDOR) is still the most common API killer: GET /runs/{id} with only “is authenticated” checks.

Sessions (server-side) vs JWT access tokens

Server sessions: opaque session id in an HttpOnly Secure cookie; server stores state (Redis/DB). Revocation is immediate (delete session). Great for first-party web apps. JWT access tokens: bearer credentials, often short-lived, scalable validation without central lookup if you only verify signature+claims — revocation is harder (short TTL, blocklist, or introspection).
text
1SESSION COOKIE (first-party web)2  Set-Cookie: session=...; HttpOnly; Secure; SameSite=Lax; Path=/3  Server: load session → user_id, tenant_id, roles4  Logout: destroy server session56JWT ACCESS + REFRESH (APIs/SPAs/mobile — one common pattern)7  access_token:  short TTL (5–15m), Authorization: Bearer8  refresh_token: longer, rotated, stored carefully (httpOnly cookie or secure storage)9  Revocation: refresh family revoke + short access TTL1011DO NOT store long-lived JWTs in localStorage if XSS is in your threat model12without accepting that any XSS becomes full account take over.

OAuth2 / OIDC in one altitude

Users authenticate via IdP (OIDC). Your app receives identity assertions and issues its own session or tokens for APIs. Do not pass the IdP’s token forever to every microservice if you can mint internal tokens with least privilege. Know authorization code + PKCE for public clients; avoid implicit flow.

RBAC and the authorization check

Roles (admin, member, viewer) map to permissions (runs:read, runs:write, billing:admin). Enforce on every mutating and sensitive read path — middleware + explicit resource checks. For multi-tenant SaaS: role is scoped to tenant/project. ABAC adds attributes (owner_id, region) when roles explode.
python
1# Pseudocode — object-level authz2def get_run(user, run_id):3	run = db.get_run(run_id)4	if run is None:5		raise NotFound()  # or 404 for both missing and foreign6	if run.tenant_id != user.tenant_id:7		raise NotFound()  # avoid cross-tenant existence oracle if required8	require_perm(user, 'runs:read', project_id=run.project_id)9	return run1011# Never: if user.is_authenticated: return db.get_run(run_id)

Service-to-service auth

Workers and sidecars need identity too: mTLS (mesh), signed service JWTs, or cloud IAM roles (AWS IAM, GCP SA) to reach queues and secret stores. Never embed a long-lived personal user token in a worker. Provider API keys for OpenAI/Anthropic live in a secret manager, rotated, scoped, and audited — not in the repo.

Common web threats (backend angle)

CSRF: cookie sessions need SameSite + anti-CSRF for state-changing routes. XSS: steals bearer tokens in JS-accessible storage. SSRF: tool-calling agents fetching URLs can hit cloud metadata — restrict egress. Prompt injection is not classic auth but can bypass tool authorization if tools trust model output as user intent — authorize tools as the user, not as the model.

API keys for product customers

Hash API keys at rest (like passwords), show once on create, prefix for support (lk_live_abc…). Scope keys (project-level). Rate limit per key. Support rotation with overlap windows. Log key id, never raw key.
Separate live vs test keys when billing or external side effects differ. Bind keys to a project (not only a user) so offboarding a human does not strand CI. Provide last_used_at and an audit stream of key creation/revocation — support will ask.

Session fixation, rotation, and logout

Rotate session ids on login privilege change. Logout must invalidate server state (and refresh-token family if used). “Delete cookie client-side only” is not logout. For stolen-session response: global logout (all sessions), device list, and short access TTLs. Interviewers poke here after you say “we use JWT.”

Principle of least privilege for LLM features

A “summarize my ticket” feature should call tools as the user with the user’s scopes — not as a superuser service account that can read all tenants. When the model asks for a tool, the backend re-checks permission on the concrete resource id in the tool args. This is authorization, not prompt engineering.

Auth testing that catches BOLA

Automated tests: user A token on user B resource → 403/404; viewer cannot POST; revoked API key → 401; expired session → 401; cross-tenant project id in body ignored or rejected. If these tests do not exist, assume the hole exists. Ship them next to the route handlers, not as a “security sprint later.”

M2M vs user-delegated access

Machine-to-machine (client credentials) is for services acting as themselves. On-behalf-of / user-delegated tokens are for “this worker acts for user U.” LLM tools that touch user data almost always need the second story — otherwise you have confused a daemon’s identity with a customer’s consent.
Document the trust boundary in the design doc: browser → API (user session), API → worker (service identity + run_id), worker → provider (vendor key). Mixing those credentials is how god-mode keys leak into the wrong layer.

Interview answers — auth

  1. 01Q: Session vs JWT? Session cookies for first-party web with instant revoke; JWT/bearer for APIs/mobile with short TTL + refresh strategy; hybrid is common.
  2. 02Q: How do you revoke JWTs? Short access TTL, refresh rotation, server blocklist/introspection for emergencies — pure stateless forever is a myth under compromise.
  3. 03Q: 401 vs 403? Unknown/invalid auth → 401; known identity lacking permission → 403. Some APIs collapse to 404 for privacy on resources.
  4. 04Q: BOLA/IDOR? Always authorize on resource tenant/owner, not only authentication. Test cross-tenant IDs in CI.
  5. 05Q: Where store tokens in SPA? Prefer httpOnly cookies via BFF; if bearer in memory, accept XSS risk; localStorage is durable XSS bait.
  6. 06Q: Service auth? mTLS or cloud workload identity; least-privilege roles; no shared god keys across environments.
  7. 07Q: RBAC explosion? Introduce resource scopes and ABAC attributes; keep a permission catalog; avoid per-user special cases in code.
  8. 08Q: API key design? Hash at rest, prefix, scopes, rotation, per-key limits, audit logs on use.
  9. 09Q: LLM tools and authz? Model proposes; backend authorizes each tool call as the user with allowlists and argument validation.
  10. 10Q: Secrets in prompts? Redact logs, encrypt sensitive fields, minimize retention, separate admin access to raw traces.
docsOWASP API Security Top 10OWASPdocsRFC 6749 — OAuth 2.0IETFdocsOWASP Session Management Cheat SheetOWASPdocsGoogle — Using OAuth 2.0 for Web Server ApplicationsGoogle

Checkpoint

A SPA stores a long-lived access JWT in localStorage. What is the primary risk called out in production reviews?

AJWT signature verification becomes impossible in browsers.BAny XSS can exfiltrate the token and replay APIs until expiry — and long TTL widens the window.CCookies are illegal for authentication under OAuth2.
Sign up free to answer and see why

Checkpoint

Endpoint GET /v1/runs/{id} checks only that a Bearer token is valid. User from tenant A requests tenant B’s run UUID. What failed?

AAuthentication only — missing object-level authorization (BOLA/IDOR class).BTLS termination — UUIDs are secret so checks are optional.CRate limiting only — add 429 and the issue is solved.
Sign up free to answer and see why

Checkpoint

A background worker needs to call the billing service. Worst design?

AUse cloud workload identity / mTLS service account with least-privilege role billing:write for that worker only.BHardcode a founder’s personal session cookie into the worker environment.CMint short-lived service JWTs signed by an internal issuer the billing service trusts.
Sign up free to answer and see why

Checkpoint

Why do short-lived access tokens pair with refresh tokens?

ABecause refresh tokens are always stored in public Git repos for convenience.BAccess tokens stay brief to limit stolen-token lifetime; refresh enables UX continuity and can be rotated/revoked server-side.COAuth forbids access tokens longer than 30 seconds in all deployments.
Sign up free to answer and see why

Checkpoint

An agent tool can fetch arbitrary URLs the model suggests. What authz/control is essential?

ATrust the model to only request safe URLs because system prompts forbid SSRF.BBackend allowlist/denylist, block link-local/metadata IPs, and authorize the tool action as the user — never as “model says so.”CDisable HTTPS so inspection is easier on the wire.
Sign up free to answer and see why

Can you explain session vs JWT, object-level authz, and service identity for an LLM worker?

New to itGetting thereConfident

Takeaways

  • AuthN ≠ AuthZ — always check the object’s tenant/owner.
  • Pick sessions vs JWT from clients and revocation needs.
  • Service identities and hashed API keys beat borrowed human cookies.
  • Agent tools need allowlists and user-scoped authorization.

Next: queues, workers, retries, backoff, DLQs, and poison messages.

Sources

Free to read · better with Enzo

Learn it with Enzo

Save your progress, answer the checkpoints, and let Enzo quiz you on what you just read.