Role-Based Access Control (RBAC)
debt(d7/e7/b7/t5)
Closest to 'only careful code review or runtime testing' (d7). Missing authorisation checks on routes/controllers are rarely caught by static tools; SAST may flag some patterns but most gaps surface only via code review or penetration testing. No detection_hints provided, so citing category-appropriate review/testing practices.
Closest to 'cross-cutting refactor across the codebase' (e7). The quick_fix names spatie/laravel-permission or Symfony Voters, but adopting these means replacing ad-hoc is_admin checks scattered across routes, controllers, middleware, and views — a cross-cutting change, not a one-line patch.
Closest to 'strong gravitational pull' (b7). Authorisation is load-bearing: every route, controller, and API endpoint consults the RBAC layer. The role/permission model shapes how features are built, and changing the model (e.g. moving to ABAC) ripples everywhere.
Closest to 'notable trap (a documented gotcha)' (t5). The misconception conflates authentication with authorisation — a common confusion that most developers eventually learn, but which causes real bugs (assuming logged-in means authorised). Other gotchas like checking roles in views compound this.
Also Known As
TL;DR
Explanation
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.
Common Misconception
Why It Matters
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.
Code Examples
// Ad-hoc checks scattered everywhere — unmaintainable
class PostController {
public function publish(Post $post) {
if ($user->type !== 'admin' && $user->type !== 'editor') {
abort(403);
}
// What if 'moderator' should also publish?
// Must find every check and update it
}
public function delete(Post $post) {
if ($user->type !== 'admin') abort(403); // different check!
}
}
// Centralised RBAC — change roles once, applies everywhere
// Migration: roles table, permissions table, role_user pivot
// Define permissions once
// Role 'editor' => ['publish-posts', 'edit-posts']
// Role 'admin' => ['publish-posts', 'edit-posts', 'delete-posts']
class PostController {
public function publish(Post $post) {
$this->authorize('publish-posts'); // checks user's roles
// Adding 'moderator' role with 'publish-posts' permission
// is a database change — no code changes needed
}
public function delete(Post $post) {
$this->authorize('delete-posts');
}
}