When RBAC's static role model isn't flexible enough, we turn to ABAC — Attribute-Based Access Control. Where RBAC asks "what role does this user have?", ABAC asks "do the attributes of this user, this resource, and this environment satisfy our policy?"
The Three Pillars of ABAC
ABAC makes access decisions by evaluating attributes — key-value pairs describing the world — against a set of policies (logical rules).
1. Subject Attributes (Who is the user?)
Properties of the entity requesting access:
- user.department = "Finance"
- user.clearance_level = "confidential"
- user.employment_type = "contractor"
2. Resource Attributes (What are they accessing?)
Properties of the thing being accessed:
- resource.classification = "high_sensitivity"
- resource.owner_department = "Finance"
- resource.contains_pii = true
3. Environment Attributes (What is the context?)
Properties of the situation at the moment of access:
- environment.time = "02:00 UTC"
- environment.network = "corporate_vpn"
- environment.system_state = "emergency"
Writing ABAC Policies
Policies are logical expressions evaluated at runtime. A policy engine (like Open Policy Agent, AWS Cedar, or a database's row-level security engine) evaluates these expressions for every access request:
# Allow a doctor to read a patient record IF:
# - The doctor's assigned ward matches the patient's ward
# - The access is happening during business hours
# - The doctor is accessing from the hospital network
ALLOW read ON PatientRecord IF:
user.ward == resource.ward
AND environment.time BETWEEN "08:00" AND "20:00"
AND environment.network == "hospital_internal"
This single policy replaces what would require dozens of RBAC roles.
RBAC vs. ABAC: Choosing the Right Tool
These models are not mutually exclusive. Most mature systems use RBAC as the foundation (for broad, stable permission categories) and layer ABAC on top (for dynamic, context-sensitive restrictions). RBAC handles "Alice is a doctor." ABAC handles "Alice can only see patients in her ward, during her shift, from the hospital network."
| Dimension | RBAC | ABAC |
|---|---|---|
| Decision basis | Static role membership | Dynamic attribute evaluation |
| Flexibility | Low — requires new roles for new cases | High — policies handle new cases |
| Auditability | High — "who has role X?" is simple | Lower — "can Alice access this?" depends on runtime context |
| Implementation complexity | Low | High |
| Best for | Stable, well-defined permission categories | Dynamic, context-sensitive access rules |
The senior engineer's insight: ABAC's power is also its danger. A policy that evaluates five attributes across three categories can produce access decisions that are nearly impossible to reason about after the fact. "Why did Alice get access to that record at 2 AM?" requires replaying the exact attribute values at that moment. Always ensure your ABAC system logs not just that access was granted, but which policy clause granted it and what attribute values were evaluated.
Interviewers at companies with complex data access requirements (healthcare, finance, government) often ask: "How would you implement row-level security so users can only see their own department's data?" A weak answer describes application-level filtering. A strong answer describes ABAC implemented at the database layer using Row-Level Security (RLS) policies — for example, PostgreSQL's CREATE POLICY — so that even if the application has a bug, the database enforces the restriction. This is defense in depth: the policy is enforced at the data layer, not just the application layer.