Skip to main content
SDMastery
intermediate10 min readUpdated 2026-06-08

Authorization

Authorization controls what authenticated users can do. RBAC, ABAC, and policy engines enforce permissions across distributed systems without hardcoding.

Diagram showing the key components and data flow in a Authorization system design
High-level overview of Authorization
Authorization

Authorization answers: what are you allowed to do? After authentication confirms identity, authorization enforces permissions. In a monolith, a simple role check suffices. In microservices, you need a consistent policy engine that every service queries — otherwise each team implements its own rules and access control becomes unpredictable. The three dominant models are RBAC (role-based), ABAC (attribute-based), and ReBAC (relationship-based, used by Google Zanzibar).

AspectDetails
What it isThe process of determining what actions an authenticated user is permitted to perform on which resources
When to useAny multi-user system, multi-tenant SaaS, API access control, data isolation between customers
When NOT to useSingle-user applications or internal tools where all users need the same level of access
Real-world exampleGoogle Zanzibar handles authorization for Google Drive, YouTube, and Cloud IAM — trillions of checks per second
Interview tipAlways separate authentication from authorization — they are different concerns with different solutions
Common mistakeHardcoding permission checks (if user.role == 'admin') throughout the codebase instead of using a policy engine
Key tradeoffGranularity vs performance — fine-grained permissions are more secure but require more checks per request

Why This Matters

Authorization failures are the second most common web vulnerability (OWASP A01:2021 Broken Access Control). In multi-tenant SaaS, one tenant seeing another's data is a company-ending bug. In microservices, authorization logic scattered across 50 services is impossible to audit. Centralizing authorization in a policy engine (OPA, Cedar, SpiceDB) lets you enforce consistent rules, audit who accessed what, and change permissions without redeploying code.

System architecture diagram for Authorization showing how services, databases, and caches connect
System architecture for Authorization

The Building Blocks

  • RBAC (Role-Based Access Control): Users are assigned roles (admin, editor, viewer), roles have permissions. Simple, widely understood, works for 80% of applications. Breaks down when permissions depend on resource ownership.
  • ABAC (Attribute-Based Access Control): Permissions depend on attributes of the user, resource, action, and context. Example: 'managers can approve expenses under $10,000 during business hours.' More flexible than RBAC but harder to reason about.
  • ReBAC (Relationship-Based Access Control): Permissions defined by relationships between objects. Google Zanzibar: 'user:alice is editor of doc:readme, editors can view.' Natural for document/file sharing systems.
  • Policy Engine: A dedicated service that evaluates authorization decisions. OPA (Open Policy Agent) uses Rego language, AWS Cedar uses a typed policy language. Decouples policy from code.
  • Permission Propagation: In microservices, the API gateway validates authentication and attaches user claims/roles. Downstream services make local authorization decisions based on those claims without calling back to the auth service.

Under the Hood

When a request arrives, the API gateway extracts the user's identity from the JWT and enriches it with roles/groups (cached from the identity provider). It forwards the request with these claims to the target service. The service calls the policy engine: "Can user X perform action Y on resource Z?" The policy engine evaluates the request against stored policies and returns allow/deny.

Step-by-step diagram showing how Authorization processes a request from start to finish
How Authorization works step by step

For performance, authorization decisions are cached. Google Zanzibar uses a distributed cache with a consistency model — it guarantees that permission changes propagate within a bounded time (called "zookies" for consistency tokens). In simpler systems, caching RBAC role lookups in Redis with a 5-minute TTL balances performance and freshness.

The critical design decision is where to enforce authorization. Gateway-level enforcement (coarse: can this user access this API?) catches most unauthorized requests cheaply. Service-level enforcement (fine: can this user edit THIS document?) handles resource-specific permissions. Most systems need both layers.

How Companies Actually Do This

Google built Zanzibar to handle authorization for Drive, YouTube, Cloud IAM, and Maps. It serves trillions of authorization checks per second with single-digit millisecond latency using a global distributed graph.

Comparison table for Authorization contrasting approaches, tradeoffs, and when to use each
Comparing key aspects of Authorization

AWS implements authorization through IAM policies — JSON documents that define who can do what on which resources. Every AWS API call is authorized through IAM, processing billions of decisions daily.

Airbnb uses a centralized authorization service called Himeji, built on SpiceDB (open-source Zanzibar). It handles complex relationships: host owns listing, guest booked listing, co-host manages listing.

Common Pitfalls

  1. Scattering authorization checks across services with inconsistent logic — one service allows access that another denies for the same user
  2. Checking only roles without verifying resource ownership — a user with 'editor' role should only edit THEIR documents, not all documents
  3. Not logging authorization denials — failed access attempts are critical security signals for detecting brute-force or privilege escalation attacks
Data flow diagram for Authorization showing how requests and responses move through the system
Data flow through Authorization

Interview Questions Worth Practicing

  1. How would you design an authorization system for a multi-tenant SaaS platform?
  2. What are the tradeoffs between RBAC and ABAC, and when would you choose each?
  3. How does Google Zanzibar achieve consistent authorization at global scale?

The Tradeoffs

  • RBAC Simplicity vs ABAC Flexibility: RBAC is easy to understand and audit but cannot express context-dependent rules. ABAC handles complex scenarios but policies become hard to reason about at scale.
  • Centralized vs Distributed Enforcement: A central policy engine ensures consistency but adds latency. Distributed enforcement (cached policies) is faster but risks stale permissions.
  • Granularity vs Performance: Object-level permissions (can user edit THIS row?) are the most secure but require a check per object. Role-level permissions are faster but coarser.
Component diagram for Authorization showing each building block and its responsibility
Key components of Authorization

How to Explain This in an Interview

Here is how I would explain Authorization in a system design interview:

Authorization decides what a user can do after authentication confirms who they are. I would implement it in two layers: the API gateway enforces coarse checks (does this user's role allow access to the /admin endpoints?), and individual services enforce fine-grained checks (can this user edit THIS specific document?). For the policy engine, I would use RBAC for most resources since it covers 80% of cases simply. For complex sharing scenarios (like Google Docs), I would use a relationship-based model similar to Zanzibar — define permissions as relationships (user:alice is editor of doc:X) and traverse the graph. I would cache authorization decisions in Redis with short TTLs and log every denial for security auditing.

Interview preparation checklist for Authorization with key points to mention and mistakes to avoid
Interview tips for Authorization

The Real-World Incident That Made This Famous

Understanding Authorization became critical after multiple high-profile production incidents at major tech companies. When systems handle millions of users, even small misunderstandings about Authorization can lead to cascading failures that cost millions in lost revenue and erode user trust. Companies like Netflix, Google, Amazon, and Meta have all invested heavily in mastering Authorization because they learned the hard way that ignoring it leads to outages.

The key lesson from these incidents: Authorization is not just a theoretical concept — it is a practical skill that separates engineers who build resilient systems from those who build fragile ones. Every major outage report from the past decade involves at least one Authorization-related design decision that was either implemented incorrectly or overlooked entirely during the initial architecture review.

Decision guide for when to choose Authorization and when alternative approaches are better
When to use Authorization

How Senior Engineers Think About This

Senior engineers approach Authorization differently from textbook definitions. Instead of memorizing rules, they build mental models. They ask: "What problem does Authorization solve? When does it fail? What are the alternatives?" This problem-first thinking leads to better design decisions because every system has unique constraints.

When evaluating Authorization in a system design context, experienced engineers consider the failure modes first. What happens when this component goes down? How does the system degrade? Is the degradation graceful or catastrophic? These questions reveal more about your understanding than any textbook definition.

The key difference between junior and senior engineers when it comes to Authorization: juniors focus on the happy path, while seniors design for what happens when things go wrong. They consider operational cost, team expertise, monitoring requirements, and how the decision will look six months from now when traffic has grown 10x.

Tradeoff analysis for Authorization listing advantages, disadvantages, and real-world considerations
Advantages and disadvantages of Authorization

Common Interview Mistakes

Mistake 1: Giving a textbook definition without context. Interviewers want to see you connect Authorization to real systems and real problems. Instead of reciting definitions, explain when and why you would use Authorization in the system you are designing.

Mistake 2: Not discussing trade-offs. Every design decision involving Authorization has trade-offs. Discuss what you gain and what you give up. Acknowledge the downsides and explain why the benefits outweigh them for your specific use case.

Mistake 3: Overcomplicating the solution. Start with the simplest approach to Authorization that meets the requirements, then add complexity only when justified. Many candidates jump to complex implementations when a simpler solution would work perfectly.

Production deployment examples of Authorization at companies like Netflix, Google, and Amazon
Real-world examples of Authorization

Production Checklist

  • Define clear metrics for measuring the effectiveness of your Authorization implementation
  • Set up monitoring and alerting that specifically tracks Authorization-related failures
  • Document your Authorization design decisions in Architecture Decision Records (ADRs)
  • Test failure scenarios related to Authorization in staging before production deployment
  • Review and update your Authorization implementation quarterly as system requirements evolve
  • Train new team members on the specific Authorization patterns used in your system
  • Establish runbooks for common Authorization-related incidents and recovery procedures

Practical Implementation for .NET Developers

In ASP.NET Core, use policy-based authorization: services.AddAuthorization(o => o.AddPolicy("CanEdit", p => p.RequireClaim("role","editor"))). Apply with [Authorize(Policy = "CanEdit")]. For resource-based authorization, implement IAuthorizationHandler<OperationAuthorizationRequirement, Document> to check ownership. For complex RBAC, use a permissions table in the database and a custom IAuthorizationHandler that queries it. Consider integrating with OpenFGA (open-source Zanzibar) via its .NET SDK for relationship-based access control.

ASP.NET Core setup: Create a service class that encapsulates the logic, register it with dependency injection, and inject it into your controllers or minimal API endpoints. The built-in DI container handles lifecycle management.

Entity Framework Core: For database interactions, EF Core provides the ORM layer. Use migrations for schema management and raw SQL for performance-critical queries. Consider Dapper for read-heavy paths where EF Core overhead matters.

Azure integration: If deploying to Azure, leverage managed services — Azure Cache for Redis, Azure SQL, Azure Service Bus, Azure Cosmos DB. These eliminate operational overhead and provide built-in monitoring through Application Insights.

Testing: Use xUnit with Testcontainers for integration tests that spin up real databases in Docker. Mock external dependencies with NSubstitute. The WebApplicationFactory class lets you test your entire HTTP pipeline in-process.

Monitoring: Add Application Insights telemetry to track request latency, dependency calls, and custom metrics. Use structured logging with Serilog to make production debugging possible:

text
Log.Information("Processing {Operation} for {ResourceId}", operation, resourceId);

This gives you searchable, structured logs in Azure Monitor or Seq.