Authentication & Authorization
In a Nutshell
Every non-trivial API must answer two distinct questions on each request: who are you? (authentication) and what are you allowed to do? (authorization). Authentication verifies identity — proving the caller is who they claim to be, via an API key, a token, or credentials. Authorization decides what that verified identity may access — which endpoints, which resources, which actions. They're often conflated but are separate concerns: you authenticate once to establish identity, then authorize every request against that identity's permissions. This topic covers these from the API-design angle — the mechanisms and patterns; the deeper security internals (OAuth2 flows, JWT structure, password handling) live in Topic 12 — Security.

How It Actually Works
Authentication vs Authorization
Authentication (AuthN): "Who are you?" → verify identity
Authorization (AuthZ): "What can you do?" → check permissions
Order matters: authenticate FIRST (establish identity),
then authorize (check that identity's rights on the resource).
A valid token (authenticated) can still be forbidden (not authorized).
| Authentication | Authorization | |
|---|---|---|
| Question | Who are you? | What may you do? |
| Checks | Identity (token, key, credentials) | Permissions (roles, scopes, policies) |
| Failure code | 401 Unauthorized | 403 Forbidden |
| When | Once per session/request to establish identity | Every request, per resource/action |
API Authentication Mechanisms
| Mechanism | How | Best For |
|---|---|---|
| API keys | A secret string sent in a header | Server-to-server, simple identification |
| Bearer tokens (JWT/opaque) | A token proving an authenticated session | User-facing APIs, SPAs, mobile |
| OAuth 2.0 | Delegated access via tokens | Third-party access, "Sign in with…" |
| mTLS | Mutual certificate authentication | High-security service-to-service |
| HMAC signatures | Sign the request with a shared secret | Webhooks, AWS-style request signing |
API key: Authorization: ApiKey sk_live_abc123
Bearer token: Authorization: Bearer eyJhbGciOi... (JWT or opaque)
API keys identify the caller (often a service or account) but carry little context; bearer tokens (typically JWTs — see OAuth2 & JWT) carry identity and often claims/scopes, and are the standard for user-facing APIs.
Authorization Models
| Model | Decides Access By | Example |
|---|---|---|
| RBAC (Role-Based) | The user's role(s) | admin can delete; viewer can only read |
| ABAC (Attribute-Based) | Attributes (user, resource, context) | "Editors in the same org, during business hours" |
| ReBAC (Relationship-Based) | Relationships between entities | "You can edit a doc you own or were shared" |
| Scopes (OAuth) | Token-granted permissions | read:orders, write:orders |
RBAC is the common default (simple, coarse-grained); ABAC/ReBAC handle fine-grained, contextual, or relationship-driven rules (like Google Docs sharing).
Token-Based Auth Flow (the Common Pattern)
1. Client authenticates once (login / OAuth) → receives a TOKEN
2. Client sends the token on EVERY subsequent request
Authorization: Bearer <token>
3. API validates the token (signature/expiry) → identity established (AuthN)
4. API checks the identity's permissions for this resource/action (AuthZ)
5. Allow (proceed) or deny (401 if bad token, 403 if forbidden)
Where the check happens matters: an API gateway commonly performs authentication centrally (validate the token once at the edge), then passes identity to backend services which enforce fine-grained authorization.
Common Pitfalls
- Confusing 401 and 403 — 401 = not authenticated (bad/missing credentials); 403 = authenticated but not permitted.
- Authorizing only at the UI — the API must enforce authorization independently; hiding a button isn't security.
- Overly broad tokens/keys — grant least privilege (narrow scopes, short-lived tokens).
- Trusting the client — never let the client assert its own permissions; the server decides.

Seeing It in Action
Scenario: Securing a multi-tenant SaaS API with token auth + RBAC.
1. Login (authentication):
POST /v1/auth/login {email, password}
→ server verifies credentials → issues a short-lived JWT (15 min) +
a refresh token. The JWT carries claims:
{ "sub": "user_42", "org": "acme", "role": "editor",
"scopes": ["read:docs","write:docs"], "exp": ... }
2. Every request carries the token:
GET /v1/orgs/acme/docs/99
Authorization: Bearer eyJ...
3. API gateway authenticates (once, at the edge):
- verify JWT signature + expiry → 401 if invalid/expired
- extract identity (user_42, org=acme, role=editor)
- forward identity to the docs-service
4. docs-service authorizes (per resource):
- Is the doc's org == token's org? (tenant isolation — critical!)
doc 99 belongs to org "acme" == token org "acme" ✅
- Does role "editor" permit the action?
GET (read) → editors can read ✅ → 200
DELETE → only "admin" can delete → 403 for an editor
Tenant isolation check prevents the classic bug: user_42 from org "acme"
must NEVER read org "globex"'s docs — even with a valid token. The
authorization layer enforces org == org on every resource access.
Why the two-layer split works: authentication is a cross-cutting concern done once at the gateway — validate the token, establish identity — so backend services don't each reimplement it. Authorization is inherently contextual to each resource (does this user's role and org permit this action on this specific document?), so it's enforced by the service that owns the resource. The most dangerous, most common failure in multi-tenant APIs is a valid-token-but-wrong-tenant access; robust authorization checks the resource's ownership against the token's identity on every request, never assuming a valid token implies permission. Getting the AuthN/AuthZ separation right is what keeps tenants' data isolated and actions properly gated.
Interview Questions
Q: What's the difference between authentication and authorization? Hint: Authentication verifies who you are (identity — via token, key, credentials); authorization decides what you're allowed to do (permissions — roles, scopes, policies). You authenticate first to establish identity, then authorize each request against that identity's rights. Failures map to 401 (not authenticated) vs 403 (authenticated but forbidden). A valid token can still be forbidden.
Q: When would you use API keys vs bearer tokens vs OAuth? Hint: API keys for simple server-to-server identification (a static secret in a header, little context). Bearer tokens (JWT/opaque) for user-facing APIs, SPAs, and mobile — they carry identity and often scopes/claims. OAuth 2.0 for delegated third-party access ("Sign in with…", granting an app limited access to your data). mTLS/HMAC for high-security or signed service/webhook calls.
Q: Compare RBAC and ABAC. Hint: RBAC grants access by role (admin/editor/viewer → permission sets) — simple, coarse-grained, the common default. ABAC decides by attributes of the user, resource, and context (e.g., "editors in the same org during business hours") — fine-grained and flexible but more complex. ReBAC (relationship-based) handles "you can edit what you own or were shared" (Google Docs style). Choose by required granularity.
Q: In a microservices system, where should authentication and authorization happen? Hint: Authentication is a cross-cutting concern best done once centrally — commonly at the API gateway (validate the token at the edge, extract identity, forward it). Authorization is contextual to each resource, so the service owning the resource enforces fine-grained permission checks (role/scope + resource ownership). This avoids each service reimplementing token validation while keeping resource-specific access decisions where the context lives.
Q: What's the most dangerous authorization bug in multi-tenant APIs, and how do you prevent it? Hint: Broken object-level / tenant authorization — a user with a valid token accessing another tenant's or user's resource (e.g., changing an ID in the URL). Prevent by checking, on every resource access, that the resource's owner/tenant matches the authenticated identity — never assume a valid token implies permission for a specific object. This is OWASP's #1 API risk (BOLA/IDOR).
References
- OWASP API Security Top 10 — the top API auth risks (BOLA, broken auth)
- Auth0: Authentication vs Authorization — clear distinction
- OAuth 2.0 — the delegated authorization standard
Dive Deeper
- Google Zanzibar (ReBAC) — relationship-based authorization at scale
- RBAC vs ABAC (NIST) — access control models compared
- Topic 12 — OAuth2 & JWT — the token internals behind API auth