{
    "slug": "rbac",
    "term": "Role-Based Access Control (RBAC)",
    "category": "security",
    "difficulty": "intermediate",
    "short": "An authorisation model where permissions are assigned to roles, and roles are assigned to users — checking 'can this role perform this action?' rather than 'can this specific user?'",
    "long": "RBAC assigns permissions to named roles (admin, editor, viewer, moderator) and assigns one or more roles to each user. When a user attempts an action, the system checks whether any of the user's roles includes the required permission. This is more maintainable than direct user-permission assignment (ACL) because changing what a role can do updates all users with that role simultaneously. Implementation patterns: flat RBAC (roles have permissions, users have roles); hierarchical RBAC (admin inherits all editor permissions); constrained RBAC (separation of duty — no user can have conflicting roles like 'requester' and 'approver'). In PHP, RBAC is implemented directly in framework Gate/Policy systems (Laravel Gates, Symfony Voters) or via libraries (spatie/laravel-permission for Laravel). The alternative to RBAC is Attribute-Based Access Control (ABAC) which evaluates policies based on attributes of the user, resource, and environment — more flexible but more complex.",
    "aliases": [
        "role-based access control",
        "roles",
        "permissions",
        "authorisation",
        "RBAC",
        "authz"
    ],
    "tags": [
        "rbac",
        "security",
        "authorisation",
        "permissions",
        "roles",
        "php",
        "laravel"
    ],
    "misconception": "RBAC and authentication are the same thing. Authentication verifies identity ('who are you?'); authorisation determines permissions ('what can you do?'). RBAC is an authorisation model — it answers the second question. A user can be fully authenticated but have no permissions to perform a specific action. The two systems are separate: authenticate first (validate credentials, establish session), then authorise each action (check roles/permissions).",
    "why_it_matters": "Without a clear authorisation model, PHP applications grow a collection of ad-hoc permission checks scattered throughout the codebase — if ($user->is_admin) here, if ($user->type === 'editor') there. When requirements change (editors should now be able to publish; admins should no longer delete users), every ad-hoc check must be found and updated. RBAC centralises permission definition: change what the 'editor' role can do in one place, and every route, controller, and API endpoint that checks that role automatically reflects the change.",
    "common_mistakes": [
        "Checking roles in views instead of controllers or middleware — business rules belong in the access control layer, not templates.",
        "Using string comparison for role checks without normalising case — 'Admin' !== 'admin'; use constants or enums for role names.",
        "Not checking authorisation on every route — a missing auth check on one endpoint is a privilege escalation vulnerability.",
        "Over-engineering with ABAC when RBAC is sufficient — start with roles and permissions; only add attribute-based policies when RBAC cannot express the required rules."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "authentication",
        "authorization",
        "rce",
        "php_sessions"
    ],
    "prerequisites": [],
    "refs": [
        "https://spatie.be/docs/laravel-permission",
        "https://symfony.com/doc/current/security/voters.html"
    ],
    "bad_code": "// Ad-hoc checks scattered everywhere — unmaintainable\nclass PostController {\n    public function publish(Post $post) {\n        if ($user->type !== 'admin' && $user->type !== 'editor') {\n            abort(403);\n        }\n        // What if 'moderator' should also publish?\n        // Must find every check and update it\n    }\n    public function delete(Post $post) {\n        if ($user->type !== 'admin') abort(403); // different check!\n    }\n}",
    "good_code": "// Centralised RBAC — change roles once, applies everywhere\n// Migration: roles table, permissions table, role_user pivot\n\n// Define permissions once\n// Role 'editor' => ['publish-posts', 'edit-posts']\n// Role 'admin'  => ['publish-posts', 'edit-posts', 'delete-posts']\n\nclass PostController {\n    public function publish(Post $post) {\n        $this->authorize('publish-posts'); // checks user's roles\n        // Adding 'moderator' role with 'publish-posts' permission\n        // is a database change — no code changes needed\n    }\n    public function delete(Post $post) {\n        $this->authorize('delete-posts');\n    }\n}",
    "quick_fix": "Use spatie/laravel-permission for Laravel or Symfony Voters for Symfony — both provide RBAC with database-backed roles and permissions out of the box",
    "severity": "high",
    "effort": "medium",
    "created": "2026-03-23",
    "updated": "2026-03-23",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/rbac",
        "html_url": "https://codeclaritylab.com/glossary/rbac",
        "json_url": "https://codeclaritylab.com/glossary/rbac.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Role-Based Access Control (RBAC)](https://codeclaritylab.com/glossary/rbac) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/rbac"
            }
        }
    }
}