Awesome-claude-code access-control-knowledge
Access Control knowledge base. Provides ACL, RBAC, ABAC, ReBAC models, multi-tenancy patterns, and PHP implementations (Symfony Voters, Laravel Gates) for security audits and generation.
install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/access-control-knowledge" ~/.claude/skills/dykyi-roman-awesome-claude-code-access-control-knowledge && rm -rf "$T"
manifest:
skills/access-control-knowledge/SKILL.mdsource content
Access Control Knowledge Base
Quick reference for access control models, authorization patterns, and PHP implementations.
Access Control Models Comparison
| Model | Full Name | Basis | Granularity | Scalability | Complexity |
|---|---|---|---|---|---|
| ACL | Access Control List | Per-resource permissions | Fine | Poor at scale | Low |
| RBAC | Role-Based Access Control | Roles assigned to users | Medium | Good | Medium |
| ABAC | Attribute-Based Access Control | Policies over attributes | Very fine | Excellent | High |
| ReBAC | Relationship-Based Access Control | Object relationships | Very fine | Excellent | High |
Decision Matrix: When to Use Which Model
| Scenario | Recommended | Why |
|---|---|---|
| Simple app, few resources | ACL | Direct, easy to implement |
| Enterprise, department-based access | RBAC | Maps to organizational roles |
| Complex policies, dynamic rules | ABAC | Flexible attribute evaluation |
| Social graphs, shared resources | ReBAC | Natural relationship modeling |
| Multi-tenant SaaS | RBAC + tenant scope | Roles per tenant |
| Healthcare, finance (compliance) | ABAC | Fine-grained audit trail |
| Document sharing (Google Docs style) | ReBAC | Owner/editor/viewer relations |
| Microservices with JWT | RBAC (claims) | Stateless, token-based |
RBAC: Role-Based Access Control
Role Hierarchy
┌─────────────────────────────────────────────────────────────────────────────┐ │ RBAC ROLE HIERARCHY │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ │ │ │ SUPER_ADMIN │ │ │ │ (all perms) │ │ │ └──────┬───────┘ │ │ │ inherits │ │ ┌──────▼───────┐ │ │ │ ADMIN │ │ │ │ (manage) │ │ │ └──────┬───────┘ │ │ ┌──────────┼──────────┐ │ │ │ inherits │ │ inherits │ │ ┌──────▼───────┐ │ ┌───────▼──────┐ │ │ │ MANAGER │ │ │ EDITOR │ │ │ │ (approve) │ │ │ (create/edit)│ │ │ └──────┬───────┘ │ └───────┬──────┘ │ │ │ │ │ │ │ └──────────┼──────────┘ │ │ ┌──────▼───────┐ │ │ │ USER │ │ │ │ (read) │ │ │ └──────┬───────┘ │ │ ┌──────▼───────┐ │ │ │ GUEST │ │ │ │ (limited) │ │ │ └──────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
Permission Inheritance
| Role | Own Permissions | Inherited From | Total Permissions |
|---|---|---|---|
| GUEST | view_public | - | 1 |
| USER | view, create | GUEST | 3 |
| EDITOR | edit, publish | USER | 5 |
| MANAGER | approve, assign | USER | 5 |
| ADMIN | manage_users, configure | MANAGER, EDITOR | 10 |
| SUPER_ADMIN | all | ADMIN | all |
RBAC PHP Implementation
<?php declare(strict_types=1); namespace Domain\Authorization; final readonly class Role { /** * @param list<Permission> $permissions * @param list<self> $parents */ public function __construct( private string $name, private array $permissions = [], private array $parents = [], ) {} public function hasPermission(Permission $permission): bool { if (in_array($permission, $this->permissions, true)) { return true; } foreach ($this->parents as $parent) { if ($parent->hasPermission($permission)) { return true; } } return false; } public function getName(): string { return $this->name; } /** @return list<Permission> */ public function getAllPermissions(): array { $permissions = $this->permissions; foreach ($this->parents as $parent) { $permissions = array_merge($permissions, $parent->getAllPermissions()); } return array_values(array_unique($permissions)); } }
ABAC: Attribute-Based Access Control
Core Concepts
| Concept | Description | Example |
|---|---|---|
| Subject | Who is requesting access | User with attributes (role, department, clearance) |
| Resource | What is being accessed | Document with attributes (classification, owner) |
| Action | Operation being performed | read, write, delete, approve |
| Environment | Contextual conditions | Time of day, IP range, MFA status |
Policy Evaluation
┌─────────────────────────────────────────────────────────────────────────────┐ │ ABAC POLICY EVALUATION │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ Request(subject, resource, action, environment) │ │ │ │ │ ▼ │ │ ┌──────────────────────┐ │ │ │ Policy Decision │ │ │ │ Point (PDP) │ ◀── Policy Store (rules) │ │ └──────────┬───────────┘ │ │ │ │ │ ┌──────┼──────┐ │ │ ▼ ▼ ▼ │ │ Policy1 Policy2 PolicyN │ │ ALLOW DENY ALLOW │ │ │ │ │ │ │ └──────┼──────┘ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ Combining Algo │ │ │ │ (deny-overrides) │ │ │ └────────┬─────────┘ │ │ ▼ │ │ DENY │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
ABAC Policy Implementation
<?php declare(strict_types=1); namespace Domain\Authorization; final readonly class AbacPolicy { public function __construct( private string $name, private string $description, /** @var list<callable(AuthorizationContext): ?bool> */ private array $rules, ) {} public function evaluate(AuthorizationContext $context): ?bool { foreach ($this->rules as $rule) { $result = $rule($context); if ($result === false) { return false; } } return true; } public function getName(): string { return $this->name; } } final readonly class AuthorizationContext { public function __construct( private array $subjectAttributes, private array $resourceAttributes, private string $action, private array $environmentAttributes = [], ) {} public function getSubjectAttribute(string $key): mixed { return $this->subjectAttributes[$key] ?? null; } public function getResourceAttribute(string $key): mixed { return $this->resourceAttributes[$key] ?? null; } public function getAction(): string { return $this->action; } public function getEnvironmentAttribute(string $key): mixed { return $this->environmentAttributes[$key] ?? null; } }
ReBAC: Relationship-Based Access Control
Google Zanzibar Model
Relationships are stored as tuples:
user:relation:object
| Tuple | Meaning |
|---|---|
| User 123 is a viewer of document 456 |
| User 123 is a member of group eng |
| Document 456 is in folder 789 |
| Members of eng group are viewers of folder 789 |
Relationship Graph
┌─────────────────────────────────────────────────────────────────────────────┐ │ ReBAC RELATIONSHIP GRAPH │ ├─────────────────────────────────────────────────────────────────────────────┤ │ │ │ user:alice ──owner──▶ document:report │ │ │ │ │ │ │ member │ parent │ │ ▼ ▼ │ │ group:engineering folder:shared │ │ │ │ │ │ │ viewer │ viewer │ │ ▼ ▼ │ │ folder:eng-docs org:acme (all members can view) │ │ │ │ Check: Can alice view document:report? │ │ Path: alice ──owner──▶ document:report ✓ (owner implies viewer) │ │ │ │ Check: Can bob view folder:shared? │ │ Path: bob ──member──▶ org:acme ──viewer──▶ folder:shared ✓ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘
Multi-Tenancy Authorization
| Pattern | Description | Isolation Level |
|---|---|---|
| Tenant-scoped roles | User has different roles per tenant | Strong |
| Shared roles, tenant filter | Global roles, data filtered by tenant | Medium |
| Tenant in JWT claims | Tenant ID in authentication token | Medium |
| Row-level security | Database enforces tenant isolation | Strong |
| Separate schemas | Each tenant has own DB schema | Strongest |
Tenant-Scoped Authorization
<?php declare(strict_types=1); namespace Domain\Authorization; final readonly class TenantPermissionChecker { public function __construct( private TenantRoleRepositoryInterface $roleRepository, ) {} public function hasPermission(string $userId, string $tenantId, Permission $permission): bool { $roles = $this->roleRepository->findRolesForUserInTenant($userId, $tenantId); foreach ($roles as $role) { if ($role->hasPermission($permission)) { return true; } } return false; } public function assertPermission(string $userId, string $tenantId, Permission $permission): void { if (!$this->hasPermission($userId, $tenantId, $permission)) { throw new AccessDeniedException( sprintf('User %s lacks %s in tenant %s', $userId, $permission->value, $tenantId), ); } } }
Symfony Voter Implementation
<?php declare(strict_types=1); namespace Infrastructure\Security\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; final class DocumentVoter extends Voter { public const string VIEW = 'DOCUMENT_VIEW'; public const string EDIT = 'DOCUMENT_EDIT'; public const string DELETE = 'DOCUMENT_DELETE'; protected function supports(string $attribute, mixed $subject): bool { return in_array($attribute, [self::VIEW, self::EDIT, self::DELETE], true) && $subject instanceof Document; } protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool { $user = $token->getUser(); if (!$user instanceof User) { return false; } /** @var Document $document */ $document = $subject; return match ($attribute) { self::VIEW => $this->canView($document, $user), self::EDIT => $this->canEdit($document, $user), self::DELETE => $this->canDelete($document, $user), default => false, }; } private function canView(Document $document, User $user): bool { if ($document->isPublic()) { return true; } return $document->getOwnerId() === $user->getId() || $user->hasRole('ROLE_ADMIN'); } private function canEdit(Document $document, User $user): bool { return $document->getOwnerId() === $user->getId() || $user->hasRole('ROLE_EDITOR'); } private function canDelete(Document $document, User $user): bool { return $document->getOwnerId() === $user->getId() || $user->hasRole('ROLE_ADMIN'); } }
Laravel Gate/Policy
<?php declare(strict_types=1); namespace App\Policies; use App\Models\Document; use App\Models\User; final class DocumentPolicy { public function view(User $user, Document $document): bool { if ($document->is_public) { return true; } return $user->id === $document->owner_id || $user->hasRole('admin'); } public function update(User $user, Document $document): bool { return $user->id === $document->owner_id || $user->hasRole('editor'); } public function delete(User $user, Document $document): bool { return $user->id === $document->owner_id || $user->hasRole('admin'); } }
Anti-Patterns
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Inline role checks | scattered in code | Use Voter/Policy abstraction |
| Hardcoded permissions | Permissions compiled into code | Store in database/config |
| Missing deny-by-default | Forgetting to deny when no rule matches | Default to DENY |
| Role explosion | Too many roles (one per use case) | Switch to ABAC or group permissions |
| Checking in views only | No server-side enforcement | Always check in backend |
| No audit logging | Cannot trace who accessed what | Log every authorization decision |
| Caching without invalidation | Stale permission grants | Event-driven cache invalidation |
| God role | Single admin role with all permissions | Granular admin sub-roles |
Common Violations Quick Reference
| Violation | Where to Look | Severity |
|---|---|---|
| No authorization on API endpoints | Controllers, routes | Critical |
| Hardcoded role names in business logic | Domain layer, services | Warning |
| Missing tenant isolation in queries | Repositories, query builders | Critical |
| No CSRF protection on state-changing forms | Form handlers, middleware | Critical |
| Permissions not cached | Voter/Policy implementations | Warning |
| No audit trail for access decisions | Authorization layer | Warning |
| Overly permissive default roles | Role configuration | Warning |
Detection Patterns
# Authorization implementations Grep: "Voter|VoterInterface|AbstractVoter" --glob "**/*.php" Grep: "Gate::define|Gate::allows|Gate::denies|@can" --glob "**/*.php" Grep: "Policy|AuthorizesRequests" --glob "**/*.php" # Role checks Grep: "hasRole|isGranted|->can\(|->cannot\(" --glob "**/*.php" Grep: "ROLE_|Permission::|PermissionEnum" --glob "**/*.php" # Inline role checks (anti-pattern) Grep: "role\s*===?\s*['\"]admin|role\s*===?\s*['\"]user" --glob "**/*.php" # Tenant isolation Grep: "tenant_id|tenantId|getTenantId" --glob "**/*.php" Grep: "TenantScope|MultiTenant|BelongsToTenant" --glob "**/*.php" # Casbin Grep: "Enforcer|casbin|model\.conf|policy\.csv" --glob "**/*.php" # Security configuration Grep: "security\.yaml|security\.php|access_control" --glob "**/*.{yaml,php}" Grep: "#\[IsGranted|@IsGranted|@Security" --glob "**/*.php" # Missing authorization Grep: "class.*Controller" --glob "**/*.php" Grep: "class.*Action" --glob "**/Action/**/*.php"
References
For detailed information, load these reference files:
— Detailed ACL, RBAC, ABAC, ReBAC analysis with scalability comparisons and PHP examplesreferences/models.md
— Symfony Voters, Laravel Gates/Policies, Casbin PHP, permission caching strategiesreferences/php-implementations.md