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

AspectRBACABAC
Decision based onUser’s roleMultiple attributes
GranularityCoarse (role-level)Fine (attribute-level)
New rules requireNew roles or permissionsNew policy rules
Scale of rolesCan explode (“role explosion”)Roles are just one attribute
ComplexitySimple to implementMore complex policy engine
Best forJob-function-based accessContext-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.

pythonsecurityauthorizationweb

See Also