Px/

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 GitHub

Permix 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:

DimensionDescriptionExample
SubjectThe caller's role or identityfinance, admin, user_123
DomainTenant or organisational scopetenant_prod, acme
ResourceThe named resource being accessedinvoice:read, project:deploy
ActionThe operation being attemptedread, 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#

bash
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#

bash
curl https://api.permix.dev/api/v1/resources/{resourceId}/policies \
  -H "Authorization: Bearer $TOKEN"

Response:

json
[
  { "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#

bash
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#

bash
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.

json
{
  "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.

bash
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:

json
{
  "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.