Model attribute-based access control in Permify — evaluate properties of users, resources, or request context to make dynamic, conditional access decisions.
Attribute-Based Access Control (ABAC) is the right choice when access decisions depend on properties of the user, resource, or environment rather than on static roles or entity relationships alone. Where RBAC asks “what role does this user have?” and ReBAC asks “how is this user related to this resource?”, ABAC asks “do the attributes of this request satisfy these conditions?”In Permify, ABAC is implemented with two schema constructs: attributes (typed properties attached to entities) and rules (boolean functions that evaluate those attributes, optionally against request context).
Access depends on a property of a resource (e.g., is_public, min_age, region).
Access depends on runtime context supplied in the request (e.g., current IP address, day of the week).
You need to express numerical ranges or set membership (e.g., balance limits, allowed locations).
Compliance rules require evaluating a combination of user, resource, and environmental attributes.
ABAC composes with RBAC and ReBAC in a single Permify schema. You can, for example, require both a valid IP range (ABAC) and organization membership (ReBAC) in the same action.
Rules are named boolean functions written in Common Expression Language (CEL). They accept the entity attribute (and optionally context.data fields from the request) and return true or false.
rule check_ip_range(ip_range string[]) { context.data.ip in ip_range}
A rule is referenced inside an action (or permission) expression:
Boolean attributes are the one exception: they can be used directly in a permission expression without a wrapping rule, because their value is the condition. All other attribute types require a rule.
A withdrawal is allowed only if the user owns the account and the requested amount does not exceed both the current balance and the 5,000 per-transaction cap.
Attribute rules can depend on permissions from parent entities. This lets you express conditions like “a department is viewable only if its budget exceeds 10,000 and its parent organization was founded after 2000”.
department.view requires check_budget to pass and the parent organization.view permission to be allowed. Permify evaluates the full chain.
You can reference a parent entity’s permission (e.g., organization.view) from a child entity’s action. You cannot directly reference the parent entity’s attribute (e.g., organization.founding_year) — only permissions traverse entity boundaries.