Menu
Course/Security & Auth/RBAC & ABAC Authorization

RBAC & ABAC Authorization

Role-Based Access Control vs Attribute-Based Access Control: design trade-offs, policy engines, permission hierarchies, and multi-tenancy.

15 min readHigh interview weight

Authentication vs Authorization

Authentication (AuthN) answers 'who are you?' and is handled by OAuth 2.0 / OIDC. Authorization (AuthZ) answers 'what are you allowed to do?' and is the subject of this lesson. These two concerns must be kept separate in your design — do not conflate them. A user can be perfectly authenticated but have zero authorization to access a specific resource.

Role-Based Access Control (RBAC)

In RBAC, permissions are assigned to roles, and roles are assigned to users. A user can have multiple roles, and a role can have multiple permissions. The key benefit is manageability: when you hire a new billing manager, you assign them the `billing-admin` role, and they immediately inherit all 47 billing-related permissions. When regulations change, you update the role once and all role members are updated.

Loading diagram...
RBAC: permissions flow from roles to users — Alice and Bob can write invoices, Carol can only read them

Hierarchical RBAC

Most real systems need role inheritance: a `super-admin` should inherit all permissions of `admin`, which inherits from `editor`, and so on. This creates a directed acyclic graph (DAG) of roles. Implementing this requires careful cycle detection and a permission resolution algorithm that traverses the inheritance graph. Libraries like Casbin (Go, Python, Node) and OPA (Open Policy Agent) handle this for you.

Attribute-Based Access Control (ABAC)

ABAC makes access decisions by evaluating policies that combine attributes of four entities: the subject (user attributes: role, department, clearance level), the resource (sensitivity, owner, classification), the action (read, write, delete), and the environment (time of day, IP address, geo-location). This enables extremely fine-grained policies that RBAC cannot express.

rego
# OPA (Open Policy Agent) — ABAC policy example
# Allow read if user's clearance >= resource sensitivity AND within business hours

package authz

default allow = false

allow {
    input.action == "read"
    input.user.clearance_level >= input.resource.sensitivity_level
    is_business_hours
    input.user.department == input.resource.owning_department
}

is_business_hours {
    hour := time.clock([time.now_ns(), "America/New_York"])[0]
    hour >= 9
    hour < 17
}

RBAC vs ABAC: Choosing the Right Model

DimensionRBACABAC
ComplexityLow — roles are intuitiveHigh — policies require careful engineering
FlexibilityLow — coarse-grainedHigh — fine-grained, context-aware
Audit easeHigh — 'who has role X?' is simpleMedium — must trace policy evaluation
PerformanceHigh — simple role lookupLower — policy evaluation overhead
Multi-tenancyRequires tenant-scoped rolesNatural — tenant ID is an attribute
Dynamic decisionsNot possible without new rolesNative — environment attributes
Best forEnterprise apps, admin panelsSaaS, healthcare, finance, government
ℹ️

Combining RBAC and ABAC

Most production systems use a hybrid: RBAC for coarse-grained access (the user must be an `editor` to write anything) and ABAC for fine-grained decisions (editors can only modify resources they own, during business hours, from approved IP ranges). This keeps the permission model auditable while enabling dynamic policy enforcement.

Multi-Tenancy Authorization

In a multi-tenant SaaS system, every authorization decision must be scoped to a tenant. The most critical bug class is cross-tenant data leakage — user Alice from TenantA accidentally reading TenantB's data. There are two common approaches: tenant-scoped roles (the user has role `admin` within tenant `T1`, expressed as `T1:admin`) or tenant as an ABAC attribute (every resource has a `tenant_id`, and every policy requires `subject.tenant_id == resource.tenant_id`).

ReBAC: Relationship-Based Access Control

Google Zanzibar (the authorization system behind Google Drive, Docs, and YouTube) introduced Relationship-Based Access Control. Access is determined by a graph of relationships between users and objects: 'User A is an editor of Folder B, which contains Document C, therefore User A can edit Document C.' This is expressive enough to model complex real-world ownership and delegation hierarchies that RBAC and ABAC struggle with. Open-source implementations include Authzed/SpiceDB, OpenFGA, and Ory Keto.

💡

Interview Tip

If an interviewer asks you to design authorization for a Google Drive-like system, name-drop Google Zanzibar and ReBAC. Explain that you need relationship tuples (user: alice, relation: editor, object: folder:marketing) and that authorization queries traverse this graph. This demonstrates awareness of state-of-the-art authorization systems beyond basic RBAC.

Storing and Enforcing Permissions

  • Centralized Policy Engine: OPA, Casbin, or SpiceDB runs as a sidecar or microservice. Every service makes an authorization call before handling a request. Adds latency (~1–5ms) but enables consistent policy enforcement.
  • JWT Claims: Embed roles/permissions in the JWT. Fast (no extra call), but permissions are stale until token refresh. Only suitable for coarse-grained, infrequently-changing permissions.
  • Middleware/Decorator: Authorization logic in API gateway or framework middleware. Request is rejected before reaching business logic. Clean separation of concerns.
  • Database Row-Level Security: For data access, PostgreSQL and others support row-level security policies enforced at the database layer — a powerful backstop against application bugs.
📝

Knowledge Check

5 questions

Test your understanding of this lesson. Score 70% or higher to complete.

Ask about this lesson

Ask anything about RBAC & ABAC Authorization