Authentication & Authorization
Authenticate identity first, then authorize actions with explicit and auditable policy.
401/403 behavior, and auditability.Definition
Authentication answers who is calling (JWT, API key, session, mTLS). Authorization answers what they can do (scopes, roles, attributes, ownership checks).
Why It Matters
- Prevents confused security design where identity and permission checks get mixed.
- Reduces privilege-escalation bugs by enforcing least-privilege decisions explicitly.
- Makes incidents easier to debug with consistent deny reasons and audit logs.
When to Use
- Any API where caller identity and permission boundaries matter.
- Multi-tenant systems with role/scope-based access control.
- Teams that need consistent
401/403semantics and audit trails.
When NOT to Use
- Pure internal scripts/tools where auth context is not applicable.
- Assuming role/scope alone can replace ownership/business-rule checks.
Code Variations
public Decision handle(Request req) {
String token = extractBearer(req);
Claims claims = jwtVerifier.verify(token); // signature, exp, iss, aud
PolicyInput in = new PolicyInput(
req.method(), req.path(), claims.subject(),
claims.scopes(), claims.tenantId()
);
if (!policyEngine.allow(in)) return Decision.forbidden("missing_scope");
req.headers().put("X-Principal-Id", claims.subject()); // gateway-generated
req.headers().put("X-Tenant-Id", claims.tenantId());
return Decision.allow(req);
}401 for invalid identity, 403 for denied permission.{
"routes": [
{ "method": "GET", "path": "/orders/**", "anyOfScopes": ["orders:read"] },
{ "method": "POST", "path": "/orders/**", "anyOfScopes": ["orders:write"] },
{ "method": "GET", "path": "/admin/**", "allOfScopes": ["admin:read", "tenant:internal"] }
]
}External headers -> sanitize
Authenticate -> Authorize -> inject trusted identity headers
Forward to service
Service still performs:
- ownership checks (user can access this order?)
- business constraints (state transitions, limits)Authentication vs Authorization
| Aspect | Authentication | Authorization |
|---|---|---|
| Core question | Who is the caller? | Can this caller perform this action? |
| Typical input | JWT/API key/mTLS cert/session token | Claims, scopes, roles, tenant, route/method |
| Failure status | 401 Unauthorized | 403 Forbidden |
| Output | Trusted identity context | Allow/deny decision + policy reason |
Common Confusions Cleared Up
Auth at edge is valuable, but domain-level checks (resource ownership, business constraints) must still be validated in the service handling that domain.
First verify token signature/expiry/audience/issuer. Then evaluate policy from claims and request context. Mixing these concerns creates brittle and unsafe logic.
Only trust headers that your gateway injects after successful auth. Strip inbound spoofable identity headers from external requests.
Variations / Implementations
JWT bearer token flow (most common)
Verify JWT (signature + exp + iss + aud), build principal, then evaluate policy from claims + request context.
mTLS service-to-service edge
Mutual TLS authenticates service identity; authorization policy maps cert/service account to allowed actions.
External policy engine (OPA/Cedar-style)
Authorization decision is delegated to policy engine for centralized updates and traceable allow/deny rules.
Common Mistakes / Anti-Patterns
- Returning
403for invalid/expired token (should be401). - Forwarding all token claims blindly to downstream services.
- Using only role names without action-level scopes (too coarse over time).
- No clock-skew tolerance for token validation, causing random auth failures.
- No audit trail for deny decisions (hard to debug incidents).
Interview Q&A
Likely Follow-up Questions
- How do you revoke JWT before expiry (blacklist, short TTL + refresh token)?
- How do you rotate signing keys (
kid, JWKS cache, rollout strategy)? - How do you model tenant isolation in policy and downstream queries?
- What gateway metrics show auth problems early (401 rate, 403 rate, policy latency)?
Quick Cheat Sheet
401 invalid/missing identity, 403 identity valid but not allowed.