RBAC
Manage Casbin role-based access control rules — assign roles to subjects, scope them to domains, and bind them to resources and actions.
Edit this page on GitHubPermix uses Casbin as its RBAC policy engine. Casbin evaluates rules in the form (subject, domain, resource, action) → allow/deny, giving you role-per-tenant isolation out of the box.
How Casbin RBAC works#
Every authorization check resolves four dimensions:
| Dimension | Description | Example |
|---|---|---|
| Subject | The caller's role or identity | finance, admin, user_123 |
| Domain | Tenant or organisational scope | tenant_prod, acme |
| Resource | The named resource being accessed | invoice:read, project:deploy |
| Action | The operation being attempted | read, write, delete, approve |
A rule grants access when (subject, domain, resource, action) matches a stored policy line. Multiple matching rules are OR-combined — access is allowed if any rule matches.
Managing RBAC rules#
Create a rule#
curl -X POST https://api.permix.dev/api/v1/resources/policies \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sub": "finance",
"dom": "tenant_prod",
"obj": "invoice:read",
"act": "read",
"effect": "allow"
}'Get rules for a resource#
curl https://api.permix.dev/api/v1/resources/{resourceId}/policies \
-H "Authorization: Bearer $TOKEN"Response:
[
{ "sub": "finance", "dom": "tenant_prod", "obj": "invoice:read", "act": "read", "effect": "allow" },
{ "sub": "admin", "dom": "tenant_prod", "obj": "invoice:read", "act": "delete", "effect": "allow" }
]Update a rule#
curl -X PUT https://api.permix.dev/api/v1/resources/policies \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sub": "finance",
"dom": "tenant_prod",
"obj": "invoice:read",
"act": "write",
"effect": "allow"
}'Delete a rule#
curl -X DELETE https://api.permix.dev/api/v1/resources/policies \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sub": "finance",
"dom": "tenant_prod",
"obj": "invoice:read",
"act": "read"
}'Resource registration and default roles#
Resources are registered at startup by the Java SDK (or manually via the API). The defaultRoles field bootstraps an initial set of RBAC rules so access control is in place before any manual configuration.
{
"name": "invoice:read",
"displayName": "Read Invoice",
"serviceName": "invoice-service",
"defaultRoles": ["finance", "admin"]
}This creates two Casbin rules automatically: (finance, *, invoice:read, read) and (admin, *, invoice:read, read).
Checking access#
The decision endpoint evaluates both RBAC and ABAC engines. RBAC is always evaluated; ABAC adds attribute-based refinement on top.
curl -X POST https://api.permix.dev/api/v1/check \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"subject": "user_123",
"resource": "invoice:read",
"action": "read",
"domain": "tenant_prod"
}'Response:
{
"decision": "allow",
"matched_rule_id": "3f7a1b2c-...",
"reason": "RBAC policy matched"
}Domain scoping#
Every Casbin rule is bound to a domain. In SaaS mode, domain comes from the domain_claim in the JWT. In self-hosted mode, you set it explicitly in the check request or leave it as the default implicit tenant.
This means the same role name can exist in multiple tenants without conflict — admin in tenant_acme and admin in tenant_northstar are independent Casbin subjects.
Combining RBAC with ABAC#
RBAC defines coarse-grained role permissions. ABAC lets you add fine-grained attribute conditions on top — for example, allowing the finance role to read invoices only when user.department == "Finance".
See ABAC for condition tree syntax and the priority/conflict resolution model.