Custom IAM Overview
Passport's IAM system is extensible — plug in custom permission resolvers for ABAC rules and custom role providers for dynamic runtime role assignment, without replacing the built-in system.
Why Extend IAM?
The built-in role-based system works well for stable, predictable access patterns. Custom IAM extensions are needed when:
Attribute-Based Conditions
Access depends on user attributes that change — department, project assignment, clearance level, employment type. RBAC cannot express "Finance employees can access payroll — contractors cannot".
Dynamic Role Assignment
Roles derive from external system state — a user is a "project manager" for Project X only when they have an open project in the ERP. Static role assignment cannot capture this.
Time or Location Constraints
Access is restricted to business hours, specific IP ranges, or geographic regions. These environmental conditions cannot be expressed in role definitions.
Cross-System Authorization
The authorization decision requires consulting an external system (HR database, project tracker, clearance registry) that is not part of Passport's identity data.
RBAC vs. ABAC
| Aspect | RBAC (Built-In) | ABAC (Custom Extension) |
|---|---|---|
| Access decision based on | User's assigned roles | User attributes + resource attributes + environment |
| Rule flexibility | Low — role membership is binary | High — any boolean expression |
| Administrative overhead | Low — assign/remove roles | Higher — maintain attribute data and rules |
| Performance | Very fast (JWT claims) | Slower (external lookups possible) |
| Auditability | Clear — role assignment log | Complex — rule evaluation log needed |
Extension Points
// Two extension points — implement one or both
// 1. ICustomPermissionResolver — adds ABAC rules to the evaluation pipeline
public interface ICustomPermissionResolver
{
Task<PermissionResolution> ResolveAsync(
PermissionContext context,
CancellationToken ct = default);
}
// 2. ICustomRoleProvider — adds dynamic roles to a user at evaluation time
public interface ICustomRoleProvider
{
Task<IReadOnlyList<string>> GetRolesAsync(
string userId,
string tenantId,
CancellationToken ct = default);
}
// Resolution outcomes
public enum PermissionResolution
{
Allow, // Explicitly allow — stops pipeline evaluation
Deny, // Explicitly deny — stops pipeline evaluation
Defer // No opinion — continue to next resolver
}
Pipeline Position
Custom extensions are called after the built-in role/permission check, unless configured with Priority.Before:
// Default evaluation order:
// 1. IIdentityProvider — resolve identity
// 2. IMembershipProvider — resolve built-in roles
// 3. ICustomRoleProvider(s) — add dynamic roles (merged)
// 4. IPermissionProvider — resolve permissions from all roles
// 5. ICustomPermissionResolver(s) — ABAC rules (short-circuit on Allow/Deny)
// 6. IAccessDecisionProvider — optional final gate
Custom IAM extensions build on the core IAM model. Read Guide3: IAM first to understand the evaluation pipeline, permission string format, and the six provider interfaces before implementing custom extensions.