Skip to content
bitzorcas
EN

Concept

Authorization

Multi-strategy authorization — RBAC (role-based), ABAC (attribute-based), AppScope (application-level), and ReBAC (relationship-based) policy evaluators with fail-closed default.

Last updated

BitzOrcas implements a four-strategy authorization pipeline that evaluates policies in sequence. The system is fail-closed — if no evaluator explicitly allows access, the request is denied.

Architecture

Request → AuthorizationPipelineBehavior
├── RbacPolicyEvaluator (role → permission)
├── AppScopePolicyEvaluator (cross-tenant app scope)
├── AbacPolicyEvaluator (context-aware rules)
└── ReBacPolicyEvaluator (relationship-graph)
IAuthorizationDecisionService → Allow / Deny

Four strategies

EvaluatorStrategyDescription
RbacPolicyEvaluatorRole-Based ACMaps user roles to permissions via SysRoleModulePermission
AppScopePolicyEvaluatorApplication ScopeCross-tenant application-level permissions
AbacPolicyEvaluatorAttribute-BasedContext-aware rules (resource owner, time, IP)
ReBcPolicyEvaluatorRelationship-BasedGraph-based access (e.g., “is member of channel”)

RBAC model

The primary authorization model:

User → Roles → RoleType → SysRoleModulePermission → Permission

Permission format

// Module + Action pattern
"ticket.create"
"ticket.view"
"ticket.assign"
"chat.message.send"
"chat.channel.manage"
"file.upload"

Permission matrix

Defined via CSV seed data (sys_role_module_permission.csv):

Role Typeticket.createticket.viewticket.assignticket.manage
Admin
Operator
EndUser✅ (own)

Data scope

IDataScopeResolver determines how much data a user can access:

public enum DataScope
{
Own, // Only own data (e.g., own tickets)
Tenant, // All data in tenant
CrossTenant // All tenants (admin/auditor)
}

AuthorizationPipelineBehavior

Mediator pipeline behavior that enforces authorization on every command/query:

// Registered in Mediator pipeline (position 2)
typeof(AuthorizationPipelineBehavior<,>)

It evaluates the authorization decision service before the handler executes.

Module-level permissions

Each module defines its own permission constants:

// Tickets module
public static class TicketPermissions
{
public const string Create = "ticket.create";
public const string View = "ticket.view";
// ...
}
// Chat module
public static class ChatPermissions
{
public const string ChannelCreate = "chat.channel.create";
// ...
}

See also