RBAC Middleware and Permission System
RBAC Middleware and Permission System
Relevant source files
The following files were used as context for generating this wiki page:
- AGENTS.md
- README.md
- db-meta/patches/00000000000000_init_database.sql
- docs/gitflow.md
- src/modules/auth/README.md
- src/modules/auth/oidc-client.ts
- src/modules/auth/permissions.ts
- src/modules/auth/rbac.middleware.ts
- src/modules/auth/role-mapping-repo.ts
- src/modules/auth/role_mapping_entity.ts
- src/modules/auth/user-profile-repo.ts
The Primebrick backend implements a robust Role-Based Access Control (RBAC) system designed for granular security, wildcard-based permission matching, and seamless integration with external Identity Providers (IDP) like Casdoor. The system follows a declare-first policy where every route must explicitly state its required permissions via a specialized middleware.
Permission Registry and Structure
The system uses a single source of truth for all available permissions defined in the Permission enum. Permissions follow a hierarchical dot-notation pattern: module.action.granularity src/modules/auth/permissions.ts:88-89.
Permission Format Examples
customers.read.all: List all customers AGENTS.md:91.customers.read.audit: Access customer audit trails AGENTS.md:93.customers.delete.bulk: Perform bulk deletion operations AGENTS.md:99.*: A global wildcard matching all permissions (effectively a super-user) AGENTS.md:110.
Permission Sentinels
Two pseudo-permissions act as sentinels and are handled directly by the middleware logic rather than role expansion src/modules/auth/permissions.ts:22-23:
Permission.PUBLIC(_public): Endpoint is reachable without a JWT. InGATEWAYmode, the gateway secret is still verified src/modules/auth/permissions.ts:37.Permission.AUTHENTICATED_USER(_authenticated_user): Any caller with a valid token passes, regardless of specific roles src/modules/auth/permissions.ts:39.
Sources: src/modules/auth/permissions.ts:34-87, AGENTS.md:88-104
Role Mappings and Expansion
Role-to-permission mappings are stored in the role_mappings table src/modules/auth/role_mapping_entity.ts:16. This table decouples IDP roles (e.g., Casdoor roles) from internal system permissions.
Role Mapping Table Structure
| Column | Type | Description |
|---|---|---|
idp_role | varchar(255) | Exact role name from the IDP (e.g., administrators, guest) src/modules/auth/role_mapping_entity.ts:24. |
permissions | jsonb | Array of permission strings or wildcard patterns src/modules/auth/role_mapping_entity.ts:30. |
is_admin | boolean | Flag for Admin Bypass. If true, all permission checks are skipped src/modules/auth/role_mapping_entity.ts:33. |
Permission Expansion Flow
When a user authenticates, the expandPermissions function resolves the user's IDP roles into a flat set of permission patterns and an isAdmin flag src/modules/auth/permissions.ts:157-160.
Sources: src/modules/auth/role_mapping_entity.ts:18-49, src/modules/auth/permissions.ts:157-179, src/modules/auth/role-mapping-repo.ts:29-44
RBAC Middleware (rbacHandler)
The rbacHandler is the primary interface for securing routes. It orchestrates gateway validation, user authentication, and permission evaluation src/modules/auth/rbac.middleware.ts:4-6.
Logical Semantics
- OR (Default): User passes if they hold at least one of the declared permissions src/modules/auth/rbac.middleware.ts:87.
- AND: User must hold all declared permissions. Invoked via
rbacHandler.all([...])src/modules/auth/rbac.middleware.ts:89.
The Evaluation Pipeline
- Gateway Check: If
AUTH_MODE=GATEWAY, validates theX-Gateway-Secretsrc/modules/auth/rbac.middleware.ts:120-131. - Auth Check: Skips for
PUBLIC, otherwise validates JWT/Headers and populatesreq.usersrc/modules/auth/rbac.middleware.ts:140-145. - Admin Bypass: If
req.user.isAdminis true, the request is immediately authorized src/modules/auth/rbac.middleware.ts:172-175. - Pattern Matching: Evaluates
req.user.permissionsagainst the route requirements usingisPermissionGrantedsrc/modules/auth/rbac.middleware.ts:180-183.
Code-to-System Mapping: Permission Enforcement
Code
Sources: src/modules/auth/rbac.middleware.ts:92-195, src/modules/auth/permissions.ts:132-146
Wildcard Matching Logic
The system supports the * wildcard to grant access to entire modules or action groups. The matchesWildcard function converts these patterns into Regular Expressions for evaluation src/modules/auth/permissions.ts:116-123.
- Logic:
customers.read.*is converted to/^customers\.read\..*$/src/modules/auth/permissions.ts:102. - Performance: The system first attempts an exact match (fast path) before iterating through wildcard patterns src/modules/auth/permissions.ts:134-136.
Permission Matching Flow
Code
Sources: src/modules/auth/permissions.ts:100-123, src/modules/auth/permissions.ts:132-146
Operational Guide: Adding New Permissions
To introduce a new permission to the system, follow these steps:
- Define the Constant: Add the new permission string to the
Permissionobject insrc/modules/auth/permissions.tssrc/modules/auth/permissions.ts:42-87. - Protect the Route: Apply the
rbacHandlerto the target Express route:
src/modules/auth/rbac.middleware.ts:39-43Code - Update Mappings: Add the permission to the relevant roles in the
role_mappingsdatabase table using SQL or theRoleMappingRepo.upsertMappingmethod src/modules/auth/role-mapping-repo.ts:49-54. - Reload: If the application uses a cache for role mappings, restart the server to ensure the
RoleMappingRepoloads the latest data AGENTS.md:148.
Sources: src/modules/auth/permissions.ts:16-20, AGENTS.md:139-145, src/modules/auth/role-mapping-repo.ts:49-75