Attribute-Based Access Control in Python — Core Concepts
What ABAC solves
Role-Based Access Control works well when permissions align with job titles. But real-world authorization often depends on context: which resource, when, from where, and under what conditions.
Consider these rules that RBAC struggles with:
- “Managers can approve expenses under $10,000; directors approve up to $100,000”
- “Employees can access their own HR records but not others’”
- “External contractors can only access the system during business hours”
- “Documents marked ‘confidential’ require VP-level clearance”
ABAC evaluates attributes from multiple sources to make these decisions. It’s the natural evolution when your authorization requirements outgrow simple role checks.
The four attribute categories
Subject attributes — properties of the person making the request. Role, department, clearance level, employment type, manager status.
Resource attributes — properties of the thing being accessed. Document classification, owner, department, creation date, sensitivity level.
Action attributes — what the subject wants to do. Read, write, delete, approve, transfer.
Environment attributes — contextual conditions. Current time, IP address, device type, network zone, threat level.
Policy structure
An ABAC policy is essentially: IF (conditions on attributes) THEN (permit or deny).
Policy: "Document Access"
Target: action == "read" AND resource.type == "document"
Rule 1: PERMIT if subject.clearance >= resource.classification
Rule 2: DENY if environment.time NOT IN resource.access_hours
Rule 3: DENY if subject.department != resource.department
AND resource.classification == "confidential"
Multiple rules combine using algorithms: deny-overrides (any deny wins), permit-overrides (any permit wins), or first-applicable (first matching rule wins).
ABAC vs. RBAC
| Aspect | RBAC | ABAC |
|---|---|---|
| Decision based on | User’s role | Multiple attributes |
| Granularity | Coarse (role-level) | Fine (attribute-level) |
| New rules require | New roles or permissions | New policy rules |
| Scale of roles | Can explode (“role explosion”) | Roles are just one attribute |
| Complexity | Simple to implement | More complex policy engine |
| Best for | Job-function-based access | Context-dependent access |
In practice, most systems combine both. RBAC handles the common cases, ABAC handles the exceptions and fine-grained rules.
Simple Python implementation
from dataclasses import dataclass
from datetime import datetime
@dataclass
class AccessRequest:
subject: dict # {"role": "doctor", "department": "cardiology", ...}
resource: dict # {"type": "patient_record", "department": "cardiology", ...}
action: str # "read", "write", "delete"
environment: dict # {"time": datetime, "ip": "10.0.1.50", ...}
class Policy:
def evaluate(self, request: AccessRequest) -> str:
"""Return 'permit', 'deny', or 'not_applicable'."""
raise NotImplementedError
class DoctorPatientRecordPolicy(Policy):
def evaluate(self, request: AccessRequest) -> str:
if (request.action == "read"
and request.resource.get("type") == "patient_record"
and request.subject.get("role") == "doctor"):
# Must be same department
if request.subject["department"] != request.resource["department"]:
return "deny"
# Must be during working hours
hour = request.environment["time"].hour
if not (7 <= hour <= 19):
return "deny"
return "permit"
return "not_applicable"
Policy Decision Point (PDP) and Policy Enforcement Point (PEP)
ABAC architecture separates two concerns:
PDP — evaluates policies and returns permit/deny decisions. This is where policies live.
PEP — sits in front of your application and enforces the PDP’s decisions. This is typically middleware or a decorator.
Separating them means you can update policies without changing application code, and the same PDP can serve multiple applications.
Common misconception
“ABAC replaces RBAC.” Most production systems use ABAC as a layer on top of RBAC, not a replacement. Roles remain one of the most useful subject attributes. ABAC adds the ability to consider resource properties, environmental conditions, and relationships that pure RBAC can’t express. Start with RBAC, add ABAC policies where role-based rules aren’t enough.
The one thing to remember: ABAC evaluates combinations of subject, resource, action, and environment attributes to make authorization decisions — enabling context-aware rules that go far beyond what job-title-based roles can express.
See Also
- Python Api Key Management Why apps use special passwords called API keys, and how to keep them safe — explained with a library card analogy
- Python Audit Logging Learn Audit Logging with a clear mental model so your Python code is easier to trust and maintain.
- Python Bandit Security Scanning Why Bandit Security Scanning helps Python teams catch painful mistakes early without slowing daily development.
- Python Clickjacking Prevention How invisible website layers trick you into clicking the wrong thing, and how Python apps stop it
- Python Content Security Policy How websites create a guest list for scripts and styles to block hackers from sneaking in malicious code