Claude
Skills
Sign in
Back

authorization-models

Included with Lifetime
$97 forever

Comprehensive authorization guidance covering RBAC, ABAC, ACL, ReBAC, and policy-as-code patterns. Use when designing permission systems, implementing access control, or choosing authorization strategies.

General

What this skill does


# Authorization Models Skill

## Overview

This skill provides comprehensive guidance on authorization models and access control patterns. Authorization determines what authenticated users can do within a system.

**Key Principle:** Authorization should be declarative, centralized, and auditable.

## When to Use This Skill

- Designing a permission system from scratch
- Choosing between RBAC, ABAC, ACL, or ReBAC
- Implementing policy-as-code with OPA
- Migrating from simple role checks to fine-grained authorization
- Implementing the principle of least privilege
- Designing multi-tenant authorization
- Building a Zanzibar-style permission system

## Authorization Model Comparison

| Model | Best For | Complexity | Scalability | Flexibility |
|-------|----------|------------|-------------|-------------|
| **ACL** | File systems, simple resources | Low | Medium | Low |
| **RBAC** | Enterprise apps, clear job roles | Medium | High | Medium |
| **ABAC** | Complex policies, dynamic rules | High | High | High |
| **ReBAC** | Social graphs, document sharing | Medium-High | Very High | High |

## Quick Decision Tree

```text
Need authorization model?
├── Simple resource ownership?
│   └── ACL (Access Control Lists)
├── Clear organizational roles?
│   └── RBAC (Role-Based Access Control)
├── Complex, context-dependent rules?
│   └── ABAC (Attribute-Based Access Control)
└── Relationship-based access (sharing, hierarchies)?
    └── ReBAC (Relationship-Based Access Control)
```

## Role-Based Access Control (RBAC)

### Core Concepts

```csharp
/// <summary>
/// Fine-grained permissions for RBAC.
/// </summary>
[Flags]
public enum Permission
{
    None = 0,
    Read = 1,
    Create = 2,
    Update = 4,
    Delete = 8,
    Admin = 16,
    Approve = 32,
    Publish = 64,

    // Common combinations
    ReadWrite = Read | Update,
    Editor = Read | Create | Update,
    FullAccess = Read | Create | Update | Delete | Admin
}

/// <summary>
/// Role with associated permissions.
/// </summary>
public sealed record Role(string Name, Permission Permissions, string Description = "");

/// <summary>
/// Standard roles definition.
/// </summary>
public static class StandardRoles
{
    public static readonly Role Viewer = new("viewer", Permission.Read, "Read-only access");
    public static readonly Role Editor = new("editor", Permission.Editor, "Can create and edit content");
    public static readonly Role Admin = new("admin", Permission.FullAccess, "Full administrative access");

    public static readonly IReadOnlyDictionary<string, Role> All = new Dictionary<string, Role>
    {
        [Viewer.Name] = Viewer,
        [Editor.Name] = Editor,
        [Admin.Name] = Admin
    };
}
```

### RBAC Implementation

```csharp
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

/// <summary>
/// Simple RBAC authorization service.
/// </summary>
public sealed class RbacAuthorizer
{
    private readonly Dictionary<string, HashSet<string>> _userRoles = new();

    public void AssignRole(string userId, string role)
    {
        if (!_userRoles.TryGetValue(userId, out var roles))
        {
            roles = new HashSet<string>();
            _userRoles[userId] = roles;
        }
        roles.Add(role);
    }

    public bool HasPermission(string userId, Permission permission)
    {
        if (!_userRoles.TryGetValue(userId, out var userRoles))
            return false;

        foreach (var roleName in userRoles)
        {
            if (StandardRoles.All.TryGetValue(roleName, out var role) &&
                role.Permissions.HasFlag(permission))
            {
                return true;
            }
        }
        return false;
    }

    public bool HasRole(string userId, string role) =>
        _userRoles.TryGetValue(userId, out var roles) && roles.Contains(role);
}

/// <summary>
/// ASP.NET Core authorization requirement for permissions.
/// </summary>
public sealed class PermissionRequirement(Permission permission) : IAuthorizationRequirement
{
    public Permission Permission { get; } = permission;
}

/// <summary>
/// Handler for permission-based authorization.
/// </summary>
public sealed class PermissionHandler(RbacAuthorizer authorizer) : AuthorizationHandler<PermissionRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        PermissionRequirement requirement)
    {
        var userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
        if (userId is not null && authorizer.HasPermission(userId, requirement.Permission))
        {
            context.Succeed(requirement);
        }
        return Task.CompletedTask;
    }
}

// Usage with attribute
[Authorize(Policy = "RequireCreate")]
[HttpPost("articles")]
public IActionResult CreateArticle([FromBody] ArticleDto article)
{
    // Only users with CREATE permission can access
    return Ok();
}
```

### Hierarchical RBAC

```csharp
/// <summary>
/// Role with inheritance support.
/// </summary>
public sealed class HierarchicalRole(
    string name,
    Permission directPermissions,
    HierarchicalRole? parent = null)
{
    public string Name { get; } = name;
    public HierarchicalRole? Parent { get; } = parent;

    /// <summary>
    /// Get all permissions including inherited from parent roles.
    /// </summary>
    public Permission AllPermissions
    {
        get
        {
            var permissions = directPermissions;
            var current = Parent;
            while (current is not null)
            {
                permissions |= current.AllPermissions;
                current = current.Parent;
            }
            return permissions;
        }
    }
}

// Role hierarchy: admin > editor > viewer
var viewerRole = new HierarchicalRole("viewer", Permission.Read);
var editorRole = new HierarchicalRole("editor", Permission.Create | Permission.Update, viewerRole);
var adminRole = new HierarchicalRole("admin", Permission.Delete | Permission.Admin, editorRole);

// adminRole.AllPermissions includes all permissions from parent roles
```

## Attribute-Based Access Control (ABAC)

### Core Concepts

```csharp
using System.Collections.Immutable;

/// <summary>
/// Context for an access decision.
/// </summary>
public sealed record AccessRequest(
    ImmutableDictionary<string, object> Subject,     // Who is requesting
    ImmutableDictionary<string, object> Resource,    // What they're accessing
    string Action,                                    // What they want to do
    ImmutableDictionary<string, object> Environment  // Context (time, location, etc.)
)
{
    public T GetSubjectAttribute<T>(string key, T defaultValue = default!) =>
        Subject.TryGetValue(key, out var value) && value is T typed ? typed : defaultValue;

    public T GetResourceAttribute<T>(string key, T defaultValue = default!) =>
        Resource.TryGetValue(key, out var value) && value is T typed ? typed : defaultValue;

    public T GetEnvironmentAttribute<T>(string key, T defaultValue = default!) =>
        Environment.TryGetValue(key, out var value) && value is T typed ? typed : defaultValue;
}

/// <summary>
/// Policy effect type.
/// </summary>
public enum PolicyEffect { Permit, Deny }

/// <summary>
/// Attribute-based policy evaluation.
/// </summary>
public sealed class AbacPolicy(
    string name,
    Func<AccessRequest, bool> condition,
    PolicyEffect effect = PolicyEffect.Permit)
{
    public string Name { get; } = name;

    /// <summary>
    /// Return effect if condition matches, null otherwise.
    /// </summary>
    public PolicyEffect? Evaluate(AccessRequest request) =>
        condition(request) ? effect : null;
}
```

### ABAC Policy Examples

```csharp
// Policy: Only managers can approve expenses over $1000
var managerApprovalPolicy = new AbacPolicy(
    name: "manager_approval",
    condition: req =>
        req.Action == "approve" &&
        req.GetResourceAttribute<string>("type") == "expense" &&
      

Related in General