Skip to main content

Attribute-Based Access Control (ABAC)

ABAC evaluates attributes of the subject (user), resource, action, and environment (time, IP, day of week) against declarative policies. Use it when access decisions depend on dynamic context — not just static role membership. For example: "engineering users can read internal APIs during business hours", or "documents classified secret require clearance level 3 and a completed background check".

Reach for ABAC when RBAC alone cannot express the rule because the answer depends on who is asking, what they are accessing, and the surrounding context.

Quick Start

Step 1: Define Attributes

Attributes are the building blocks of policies. Declare the attributes your policies will reference — for example a department on users.

Create a
curl -X POST "https://api.example.com/orgs/{orgId}/api/v1/abac/attributes" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Department",
"attributeType": "user",
"dataType": "string",
"description": "The department the user belongs to",
"validationRules": {
"enum": ["engineering", "sales", "marketing", "finance", "hr"]
}
}'

Step 2: Create a Policy

A policy has a target (resourceType + action), an effect (allow or deny), a priority, and a tree of conditions that evaluate attributes.

Allow engineering team to read APIs
curl -X POST "https://api.example.com/orgs/{orgId}/api/v1/abac/policies" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Engineering API Access",
"resourceType": "api",
"action": "read",
"effect": "allow",
"priority": 100,
"conditions": {
"operator": "AND",
"conditions": [
{
"subject": "user.department",
"operator": "equals",
"value": "engineering"
}
]
}
}'

Step 3: Check Access

Call the check endpoint to evaluate all policies for the authenticated user against a resource and action.

Check if user can access an API
curl -X POST "https://api.example.com/api/v1/abac/check" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"resourceType": "api",
"resourceId": "internal-api-v1",
"action": "read"
}'
Response
{
"allowed": true,
"reason": "Policy matched: Engineering API Access",
"matchedPolicies": [
{
"id": "550e8400-e29b-41d4-a716-446655440010",
"name": "Engineering API Access",
"effect": "allow",
"priority": 100
}
],
"evaluationContext": {
"user": {
"id": "user-123",
"email": "developer@company.com",
"department": "engineering",
"roles": ["developer"]
},
"resource": {
"id": "internal-api-v1",
"type": "api"
},
"environment": {
"hour": 14,
"dayOfWeek": 3,
"isWeekend": false
}
}
}

Core Concepts

Attributes

Attributes come in three kinds:

TypeDescriptionExamples
userProperties of the callerdepartment, clearance_level, location
resourceProperties of the targetclassification, owner_department, sensitivity
environmentProperties of the request contexthour, dayOfWeek, ip

Built-in User Attributes

These are always available without defining them:

user.id # User's unique identifier
user.email # User's email address
user.roles # Array of role slugs ["admin", "developer"]
user.groups # Array of group slugs
user.permissions # Array of permission slugs
user.emailVerified # Boolean - is email verified?
user.mfaEnabled # Boolean - is MFA enabled?
user.{trait} # Any custom user trait

Built-in Environment Attributes

environment.hour # Current hour (0-23)
environment.dayOfWeek # Day of week (1=Monday, 7=Sunday)
environment.isWeekend # Boolean for Saturday/Sunday
environment.ip # Client IP address

Policies

A policy is a rule that either allows or denies a given action on a given resource type when its conditions hold.

FieldDescriptionExample
nameHuman-readable name"Engineering API Access"
resourceTypeType of resource (use * for all)"document", "api", "*"
actionAction being performed (use * for all)"read", "write", "*"
effectAllow or deny access"allow" or "deny"
priorityHigher priority evaluated first (0-1000)100
conditionsTree of attribute comparisonsSee below

Condition Operators

OperatorDescriptionExample
equalsExact matchuser.department equals "engineering"
not_equalsNot equalresource.status not_equals "archived"
inValue in arrayuser.role in ["admin", "manager"]
not_inValue not in arrayuser.country not_in ["restricted"]
containsArray contains valueuser.roles contains "admin"
not_containsArray doesn't containuser.roles not_contains "guest"
gt / ltGreater/less thanuser.level gt 2
gte / lteGreater/less or equalenvironment.hour gte 9
matchesRegex matchuser.email matches "@company\\.com$"
existsAttribute existsuser.department exists
not_existsAttribute doesn't existresource.restricted not_exists

Combining Conditions

Use AND or OR to combine conditions. Trees can be nested arbitrarily.

AND - All conditions must match
{
"operator": "AND",
"conditions": [
{"subject": "user.department", "operator": "equals", "value": "engineering"},
{"subject": "user.level", "operator": "gte", "value": 2}
]
}
OR - Any condition must match
{
"operator": "OR",
"conditions": [
{"subject": "user.roles", "operator": "contains", "value": "admin"},
{"subject": "user.roles", "operator": "contains", "value": "super-admin"}
]
}
Nested - mix AND and OR
{
"operator": "OR",
"conditions": [
{"subject": "user.roles", "operator": "contains", "value": "admin"},
{
"operator": "AND",
"conditions": [
{"subject": "user.department", "operator": "equals", "value": "engineering"},
{"subject": "user.level", "operator": "gte", "value": 3}
]
}
]
}

Policy Examples

Department-Based Access

Allow engineering department users to read internal or public APIs.

{
"name": "Engineering API Access",
"resourceType": "api",
"action": "read",
"effect": "allow",
"priority": 100,
"conditions": {
"operator": "AND",
"conditions": [
{
"subject": "user.department",
"operator": "equals",
"value": "engineering"
},
{
"subject": "resource.classification",
"operator": "in",
"value": ["internal", "public"]
}
]
}
}

Clearance-Based Access

Users with clearance level 3 or higher, a passed background check, may read classified documents.

{
"name": "Classified Document Access",
"resourceType": "document",
"action": "read",
"effect": "allow",
"priority": 100,
"conditions": {
"operator": "AND",
"conditions": [
{
"subject": "user.clearance_level",
"operator": "gte",
"value": 3
},
{
"subject": "resource.classification",
"operator": "equals",
"value": "classified"
},
{
"subject": "user.background_check",
"operator": "equals",
"value": true
}
]
}
}

Business Hours Restriction

Deny access to sensitive data outside 9 AM – 5 PM on weekdays.

{
"name": "Business Hours Only",
"resourceType": "sensitive-data",
"action": "*",
"effect": "deny",
"priority": 200,
"conditions": {
"operator": "OR",
"conditions": [
{
"subject": "environment.hour",
"operator": "lt",
"value": 9
},
{
"subject": "environment.hour",
"operator": "gt",
"value": 17
},
{
"subject": "environment.isWeekend",
"operator": "equals",
"value": true
}
]
}
}
Deny Policy Priority

Under the deny-overrides combining algorithm, any matching deny wins regardless of matching allows. Use higher priority values on deny policies you want evaluated first.

Contractor Access Restrictions

Deny contractors any access outside business hours.

{
"name": "No After-Hours Contractors",
"resourceType": "*",
"action": "*",
"effect": "deny",
"priority": 200,
"conditions": {
"operator": "AND",
"conditions": [
{
"subject": "user.employment_type",
"operator": "equals",
"value": "contractor"
},
{
"operator": "OR",
"conditions": [
{"subject": "environment.hour", "operator": "lt", "value": 9},
{"subject": "environment.hour", "operator": "gt", "value": 17},
{"subject": "environment.isWeekend", "operator": "equals", "value": true}
]
}
]
}
}

Admin Override

Allow admins access to everything, at the highest priority.

{
"name": "Admin Full Access",
"resourceType": "*",
"action": "*",
"effect": "allow",
"priority": 1000,
"conditions": {
"operator": "OR",
"conditions": [
{"subject": "user.roles", "operator": "contains", "value": "admin"},
{"subject": "user.roles", "operator": "contains", "value": "super-admin"}
]
}
}

API Reference

Check Access

POST /api/v1/abac/check

Evaluate ABAC policies for the current user against a resource and action.

Request
curl -X POST "https://api.example.com/api/v1/abac/check" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"resourceType": "document",
"resourceId": "doc-123",
"action": "read",
"context": {
"resource": {
"classification": "internal"
}
}
}'
FieldTypeRequiredDescription
resourceTypestringYesType of resource being accessed
resourceIdstringNoSpecific resource ID (optional for type-level checks)
actionstringYesAction being performed (read, write, delete, etc.)
contextobjectNoAdditional context to supplement attribute values

Bulk Check

POST /api/v1/abac/check-bulk

Check up to 100 resource/action pairs in one request.

curl -X POST "https://api.example.com/api/v1/abac/check-bulk" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{"resourceType": "document", "resourceId": "doc-1", "action": "read"},
{"resourceType": "document", "resourceId": "doc-2", "action": "write"},
{"resourceType": "api", "action": "execute"}
]
}'

Set Resource Attributes

PUT /api/v1/abac/resources/{resourceType}/{resourceId}/attributes

Set the ABAC attributes for a specific resource. Policies reference these at evaluation time.

curl -X PUT "https://api.example.com/api/v1/abac/resources/document/doc-123/attributes" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"classification": "confidential",
"owner_department": "engineering",
"sensitivity": 3
}'

Get Current User Attributes

GET /api/v1/abac/my-attributes

Return all ABAC attributes for the currently authenticated user.

Response
{
"id": "user-123",
"email": "developer@company.com",
"roles": ["developer", "team-lead"],
"groups": ["engineering-team"],
"permissions": ["code.read", "code.write"],
"emailVerified": true,
"mfaEnabled": true,
"department": "engineering",
"clearance_level": 3,
"location": "us-west"
}

Set User Attribute

PUT /api/v1/abac/users/{userId}/attributes/{attributeSlug}

Set one attribute value on a user.

curl -X PUT "https://api.example.com/api/v1/abac/users/{userId}/attributes/department" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"value": "engineering"}'

Policy Evaluation

Combining Algorithm

LumoAuth evaluates ABAC using deny-overrides:

  1. Collect all policies matching the requested resourceType and action.
  2. Evaluate the conditions of each matching policy.
  3. If any matching policy has effect: deny → access denied.
  4. Otherwise, if at least one matching policy has effect: allow → access allowed.
  5. If no policies match → access denied (default-deny).
Default Deny

If no policy explicitly grants access, the request is denied. Always create explicit allow policies for intended access paths.

Priority

Policies with higher priority are evaluated first. Priority does not change the deny-overrides outcome, but it controls ordering where it matters (for example, logging and short-circuiting).

Priority RangeRecommended Use
900-1000Admin overrides, emergency access
200-300Deny policies, restrictions
100Standard allow policies
0-50Default/fallback policies

Organization Portal

Administrators manage ABAC under Access Management → ABAC Policies:

  • Dashboard — overview of policies and attributes.
  • Attributes — define custom user and resource attributes.
  • Policies — create and edit policies with a visual builder.
  • Tester — simulate requests and see which policies match.
Policy Tester

Test positive and negative cases in the Policy Tester before enabling a new policy in production.

Best Practices

  • Use higher priorities for deny policies and admin overrides; keep standard allows at priority 100.
  • Test positive and negative cases in the Policy Tester before deploying.
  • Prefer specific resourceType values over *. Wildcards are convenient but broaden the policy's reach.