Authorization
Authorization (AuthZ) determines what an authenticated identity may do — read orders, approve refunds, access tenant data.
Introduction
Authorization (AuthZ) determines what an authenticated identity may do — read orders, approve refunds, access tenant data. Models include RBAC (roles), ABAC (attributes), ACLs (resource lists), and OAuth2 scopes. HLD places policy enforcement at gateway (coarse) and service (fine-grained).
Least privilege is the guiding principle. Interviewers probe multi-tenant isolation, admin vs user paths, and policy storage (OPA, Casbin, database roles).
This lesson covers enforcement points, policy engines, and common patterns in microservices.
Understanding the topic
Key concepts
- RBAC: user has role ADMIN → permissions bundle.
- ABAC: allow if department=Finance AND amount<10000.
- OAuth2 scopes: orders:read, payments:write in token.
- Resource ownership: userId on row must match JWT sub.
- Policy-as-code: Open Policy Agent (OPA) sidecar evaluates Rego.
- Break-glass admin audit for override operations.
flowchart LRRequest --> GatewayGateway --> RBAC[Role Check]RBAC -->|allowed| ServiceRBAC -->|denied| 403
Internal architecture
Architecture overview
flowchart LRRequest --> GatewayGateway --> RBAC[Role Check]RBAC -->|allowed| ServiceRBAC -->|denied| 403
Step-by-step explanation
- Gateway validates JWT scopes for route /api/v1/admin/** requires role admin.
- Order service checks order.userId == principal.sub for GET /orders/{id}.
- Central OPA service: input {user, action, resource} → allow/deny.
- Multi-tenant: tenant_id in JWT; every query filters WHERE tenant_id = ?.
- Attribute store (LDAP/identity) syncs roles nightly; cache in Redis 5m.
- Deny-by-default: explicit allow rules only.
Informative example
Method-level authorization with Spring Security @PreAuthorize and ownership check:
@RestController@RequestMapping("/api/v1/orders")public class OrderController {private final OrderService orders;public OrderController(OrderService orders) { this.orders = orders; }@GetMapping("/{id}")@PreAuthorize("hasAuthority('orders:read')")public OrderDto get(@PathVariable UUID id, @AuthenticationPrincipal Jwt jwt) {return orders.getForUser(id, jwt.getSubject());}@PostMapping("/{id}/refund")@PreAuthorize("hasRole('SUPPORT') and @orderPolicy.canRefund(#id, authentication)")public RefundDto refund(@PathVariable UUID id) {return orders.refund(id);}}@Component("orderPolicy")public class OrderPolicy {public boolean canRefund(UUID orderId, Authentication auth) {// ABAC: support can refund under $500 or manager abovereturn true; // simplified}}
Defense in depth: gateway coarse RBAC + service fine ownership. Never trust client-sent userId.
Real-world use
Real-world use cases
- Banking: teller vs manager transaction limits.
- Healthcare: clinician accesses only assigned patients (HIPAA).
- Multi-tenant SaaS: strict tenant isolation in every query.
- Social: private profile visible only to approved followers.
Best practices
- Enforce authorization closest to data — service layer not only UI.
- Centralize policy for consistency; avoid scattered if-role checks.
- Audit deny and sensitive allow decisions.
- Test horizontal privilege escalation (access other user's id).
- Use UUID resource IDs — not enumerable sequences alone.
- Regular access reviews for admin roles.
Common mistakes
- Checking auth only at gateway — internal service bypass vulnerability.
- Trusting X-User-Id header from client without JWT validation.
- Role explosion — hundreds of roles unmaintainable; use ABAC attributes.
- Missing tenant filter — cross-tenant data leak.
- Admin endpoints on same hostname without extra MFA.
Advanced interview questions
Q1BeginnerRBAC vs ABAC?
Q2BeginnerWhere enforce authorization?
Q3IntermediateWhat is OAuth2 scope?
Q4IntermediateWhat is OPA?
Q5AdvancedDesign AuthZ for hospital EHR.
Summary
Authorization controls permitted actions after authentication. RBAC, ABAC, and scopes layer from coarse to fine control. Enforce at gateway and service; never trust client identity headers. Multi-tenant systems filter every query by tenant_id. OPA enables centralized policy-as-code. Rate limiting protects authorized APIs from abuse.