Skip to content

Authorization (Cerbos)

Islamic Open Finance™ uses Cerbos for policy-based access control across all services. This guide covers how authorization works and the different Policy Decision Point (PDP) types.

Cerbos provides fine-grained authorization through:

  • ABAC (Attribute-Based Access Control) - Decisions based on user/resource attributes
  • RBAC (Role-Based Access Control) - Decisions based on user roles
  • Policy-as-Code - Authorization rules defined in YAML
sequenceDiagram
participant Client as 🖥️ Client
participant API as 🚀 Rail API
participant PDP as 🔐 Cerbos PDP
participant DB as 💾 Database
Client->>+API: API Request
API->>+PDP: Check Authorization
Note over PDP: Evaluate policies<br/>against request context
PDP-->>-API: Decision (Allow/Deny)
alt Authorized
API->>+DB: Execute Query
DB-->>-API: Results
API-->>Client: 200 OK + Data
else Denied
API-->>Client: 403 Forbidden
end

IOF supports two types of PDPs for different deployment scenarios:

TypeNameUse CaseLatencyInfrastructure
SPDPService PDPBackend services, microservicesLow (local network)Runs as separate service/sidecar
EPDPEmbedded PDPEdge, client-side, offlineSub-millisecondWebAssembly module embedded in app

SPDPs are Cerbos server instances running in your infrastructure. Cerbos Hub acts as the management control plane, pushing pre-compiled policy bundles to PDPs.

Benefits:

  • Centralized policy management
  • Real-time policy updates
  • Comprehensive audit logging
  • High availability with multiple replicas

Configuration:

# Cerbos service configuration
hub:
credentials:
pdpId: ${CERBOS_PDP_ID}
clientId: ${CERBOS_CLIENT_ID}
clientSecret: ${CERBOS_CLIENT_SECRET}
workspaceId: ${CERBOS_WORKSPACE_ID}
deployment: production

Deployment Patterns:

PatternDescriptionUse Case
SidecarPDP container alongside each serviceMicroservices with isolation requirements
Shared ServiceCentral PDP for all backend servicesSimpler deployments, shared policies
ServerlessPDP as Lambda/Cloud FunctionEvent-driven architectures

EPDPs are WebAssembly policy bundles for local/edge authorization without network calls. Exclusive to Cerbos Hub.

Benefits:

  • Authorization checks become function calls (no network hops)
  • No separate service infrastructure needed
  • Sub-millisecond decision latency
  • Works offline/at edge

Use Cases:

  • Frontend UI element visibility
  • Client-side permission checks
  • Edge computing (Cloudflare Workers)
  • Offline-capable applications

TypeScript Integration:

import { Embedded } from "@cerbos/embedded";
// Initialize embedded PDP with bundle from Cerbos Hub
const cerbos = new Embedded(bundleFromHub, {
onDecision: (decision) => {
// Optional: Log decisions for audit
console.log("Authorization decision:", decision);
},
});
// Check permission
const decision = await cerbos.checkResource({
principal: {
id: user.id,
roles: [user.role],
attributes: {
tenantId: user.tenantId,
department: user.department,
},
},
resource: {
kind: "contract",
id: contract.id,
attributes: {
ownerId: contract.ownerId,
status: contract.status,
},
},
action: "view",
});
if (decision.isAllowed("view")) {
// Show contract details
}

Policies are defined in YAML and organized by type:

/policies/
├── resource_policies/
│ ├── contract.yaml # Contract resource permissions
│ ├── tenant.yaml # Tenant resource permissions
│ ├── workspace.yaml # Workspace resource permissions
│ └── rail_*.yaml # Per-rail permissions
├── principal_policies/
│ ├── super_admin.yaml # Super admin overrides
│ └── tenant_admin.yaml # Tenant admin policies
└── derived_roles/
├── workspace_roles.yaml
└── contract_roles.yaml
policies/resource_policies/contract.yaml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
version: default
resource: contract
rules:
- actions: ["view", "list"]
effect: EFFECT_ALLOW
roles: ["user", "admin"]
condition:
match:
expr: request.resource.attr.tenantId == request.principal.attr.tenantId
- actions: ["create", "update"]
effect: EFFECT_ALLOW
roles: ["admin", "contract_manager"]
condition:
match:
all:
of:
- expr: request.resource.attr.tenantId == request.principal.attr.tenantId
- expr: request.resource.attr.status != "executed"
- actions: ["delete"]
effect: EFFECT_ALLOW
roles: ["admin"]
condition:
match:
all:
of:
- expr: request.resource.attr.tenantId == request.principal.attr.tenantId
- expr: request.resource.attr.status == "draft"
- actions: ["execute", "approve"]
effect: EFFECT_ALLOW
roles: ["approver", "shariah_board"]
condition:
match:
all:
of:
- expr: request.resource.attr.tenantId == request.principal.attr.tenantId
- expr: request.resource.attr.status == "pending_approval"
policies/derived_roles/workspace_roles.yaml
apiVersion: api.cerbos.dev/v1
derivedRoles:
name: workspace_roles
definitions:
- name: workspace_owner
parentRoles: ["user"]
condition:
match:
expr: request.resource.attr.ownerId == request.principal.id
- name: workspace_member
parentRoles: ["user"]
condition:
match:
expr: request.principal.id in request.resource.attr.memberIds
ResourceActionsDescription
contractcreate, read, update, delete, execute, approveIslamic finance contracts
tenantcreate, read, update, deleteTenant/organization management
workspacecreate, read, update, delete, manage_membersWorkspace management
api_keycreate, read, update, delete, revokeAPI key management
compliancecheck, override, reportShariah compliance operations
governancevote, approve, escalateGovernance workflows
VariablePurposeRequired
CERBOS_URLService PDP endpointYes (backend)
CERBOS_PDP_IDPDP identifier for HubYes (Hub managed)
CERBOS_CLIENT_IDHub client credentialsYes (Hub managed)
CERBOS_CLIENT_SECRETHub client credentialsYes (Hub managed)
CERBOS_WORKSPACE_IDHub workspaceYes (Hub managed)
CERBOS_TIMEOUT_MSRequest timeout (default: 5000)No

Use the Cerbos CLI to validate and test policies:

Terminal window
# Validate policies
cerbosctl policy validate /policies/
# Run policy tests
cerbosctl policy test /policies/ --tests /tests/
# Check specific permission
cerbosctl decisions \
--principal '{"id":"user1","roles":["admin"],"attr":{"tenantId":"t1"}}' \
--resource '{"kind":"contract","id":"c1","attr":{"tenantId":"t1","status":"draft"}}' \
--action "update"
  1. Least Privilege - Grant minimum permissions needed
  2. Tenant Isolation - Always include tenant checks in policies
  3. Audit Logging - Log all authorization decisions
  4. Policy Testing - Test policies before deployment
  5. Version Control - Store policies in git with code review