How It Works
In Casbin, access control is expressed as CONF files based on the PERM metamodel (Policy, Effect, Request, Matchers). Changing how authorization works in your project is a matter of editing a configuration file. You can build custom models by combining components—for example, RBAC roles with ABAC attributes in a single model and policy set.
The PERM model has four parts: Request, Policy, Effect, and Matchers. Together they define how users and resources interact.
Request
The request definition specifies the parameters of an access request. A basic request is a tuple of three elements: subject (who is requesting), object (the resource), and action (the operation).
Example:
r = sub, obj, act
This sets the parameter names and their order for the matching logic.
Policy
The policy definition describes the shape of your access rules: field names and order.
Examples:
p = sub, obj, act or p = sub, obj, act, eft
When eft (policy effect) is omitted from the definition, the effect field in the policy file is ignored and matching policies are treated as "allow".
Matcher
The matcher defines how a request is matched against policies.
Example: m = r.sub == p.sub && r.act == p.act && r.obj == p.obj
When the request subject, object, and action match a policy’s fields, that policy’s effect (p.eft) is used. The effect is stored in p.eft.
Effect
The effect section combines the effects of all matched policies with a logical expression.
Example: e = some(where (p.eft == allow))
If any matched policy has effect "allow", the result is allow.
Another example:
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
This means: the result is allow only if at least one policy allows and none deny. If both allow and deny match, deny wins.
ACL is the simplest model in Casbin. Here is a minimal ACL model:
# Request definition
[request_definition]
r = sub, obj, act
# Policy definition
[policy_definition]
p = sub, obj, act
# Policy effect
[policy_effect]
e = some(where (p.eft == allow))
# Matchers
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
Example policy for this model:
p, alice, data1, read
p, bob, data2, write
So:
- alice can read data1
- bob can write data2
You can split matchers across lines by ending each line with \:
# Matchers
[matchers]
m = r.sub == p.sub && r.obj == p.obj \
&& r.act == p.act
The in operator is available in the Go implementation (not yet in jCasbin or Node-Casbin):
# Matchers
[matchers]
m = r.obj == p.obj && r.act == p.act || r.obj in ('data2', 'data3')
The array must have more than one element; otherwise the Go implementation may panic.
For more operators, see govaluate.