wnikk/laravel-access-rules

Fast access control for Laravel: RBAC with roles, groups and unlimited inheritance, extended to ABAC: conditions on any model, its relations and aggregates, with list filtering.
3,914 10
Install
composer require wnikk/laravel-access-rules
Latest Version:3.1.2
PHP:^8.4
License:MIT
Last Updated:Sep 22, 2026
Links: GitHub  ·  Packagist
Maintainer: Nikolya

Laravel Access Control Rules

Access Control Rules: RBAC and ABAC for Laravel

tests Latest Stable Version PHP Version Require Total Downloads License

Roles, groups and inheritance (RBAC), and since version 3 permissions that depend on data (ABAC), through the standard Laravel Gate.

$user->addPermission('orders.view');                                                      // RBAC: may or may not
$user->addPermission('orders.export', when: 'order.cost > 100 && order.items.count < 3'); // ABAC: depends on the record

A check costs 4 µs and no queries after the first one of a request, and the database filters a list in the same query that loads it.

Background. The model of this package has run in production since 2013: first on Zend Framework, then on Yii2, since 2023 as this Laravel package. Its parts are a separate owner with dynamic binding, inheritance of any depth, hybrid rules and options. The Laravel version keeps the number of classes low and uses what Laravel already has, so a check passes through little code.

Contents

If you want to read
see what it looks like What it does, What ABAC can do
decide between packages When to choose it, and when not, Alternatives, measured numbers
install and start Installation, Basic usage, Conditions (ABAC)
learn by example ABAC step by step, RBAC step by step
come from version 2 Upgrade from 2.x to 3.x: tables and the API stay compatible
exchange policies XACML 3.0
work with an AI coding agent For AI coding agents, docs/llms.txt

What does Access Control Rules support?

New in version 3

  • Conditions (ABAC): a permission or a prohibition can depend on the record, its relations of any kind and their aggregates, on the user and on the environment.
  • Filtering of lists by the same conditions, in the same query: Order::query()->allowedTo('orders.view'). A list and a detail page read one condition, so they agree.
  • A language for conditions: arithmetic, between, exact text functions, aggregates with filters over any relation, columns of pivot tables, time functions, and trees: "this category and everything under it".
  • Safe to edit in an admin panel: a condition is checked when it is saved, reads only models listed in config and never calls a method of a model that is not a relation.
  • No queries after the first check of a request: 4 µs per check against 62 µs and a query in version 2; permissions compile in 3 queries at any depth of inheritance. See Performance.
  • acr:explain tells why a check answers what it answers, acr:lint finds stored conditions that a migration or a refactoring has broken.
  • Debug mode for support sessions: Access::debug() explains every refusal and records what narrowed every allowedTo() list. It observes; decisions stay as they are.
  • XACML 3.0: export of permissions as a standard policy, import of policies with a plan of what would change. A check runs no XACML engine.
  • Guests, tenants, abilities as enums, the Access facade, rules of code and rules of an admin panel, event AccessChanged for an audit log.
  • Guidelines and a skill for AI coding agents through Laravel Boost.

Since version 2

  • Multiple user models, roles, groups and any other owners of permissions, also without a model.
  • Permissions and prohibitions, attached to users, groups or roles.
  • Permissions can be inherited with unlimited nesting from users, groups and roles.
  • Dynamic options (news.edit.2) and the magic suffix .self for authors of records.
  • Laravel gates and policies: $user->can(), @can, can: middleware, authorizeResource(). The package answers Gate with "yes" or nothing, so policies, a super administrator of the application and other packages keep working next to it.
  • Permissions caching, with a fallback to the database when the cache store is down.

What ABAC can do

An example of what the requirements might be:

Show the user all products tagged "sale" that have a comment with more than 10 likes.

Every link is polymorphic: likes belong to comments and comments to products through morphMany, tags reach products through morphToMany.

Setting this permission:

$user->addPermission('products.view',
    when: "exists(product.tags, name == 'sale') && exists(product.comments, likes.count > 10)");

The check in the controller:

$user->can('products.view', $product);                      // one loaded product, checked in memory
# -- or --
Product::query()->allowedTo('products.view')->paginate();   // the list, filtered by the database:

The SQL query generated by the model, taking into account controller parameters and access rights:

select * from "products" where (
  exists (select 1 from "tags" inner join "taggables" on "tags"."id" = "taggables"."tag_id"
          where "products"."id" = "taggables"."taggable_id" and "taggables"."taggable_type" = ? and "tags"."name" = ?)
  and exists (select 1 from "comments"
          where "products"."id" = "comments"."commentable_id" and "comments"."commentable_type" = ?
            and (select count(*) from "likes"
                 where "comments"."id" = "likes"."likeable_id" and "likes"."likeable_type" = ?) > ?))
-- bindings: ["product", "sale", "product", "comment", 10]

The configuration itself that makes such rules possible:

// config/access.php: every model a condition may read
'resources' => ['product' => Product::class, 'comment' => Comment::class, 'like' => Like::class, 'tag' => Tag::class],
// Migration or seeder: create the permission with a resource
Access::newRule('products.view', 'View products', resource: 'product');

Any tag under "sale" instead of "sale" itself: exists(product.tags, id in below('tag.name', 'sale')). The language, relations, aggregates and trees are described in Conditions.

Visual Interface

The visual interface for managing access control rules and permissions can be found at this link. It offers an intuitive and user-friendly environment for administrators to define roles, assign permissions, and configure access rules.

For detailed usage examples and instructions, refer to the example repository.

Documentation

Installation · Basic usage · Conditions (ABAC) · Performance · XACML · Upgrade from 2.x to 3.x

Tutorials: RBAC step by step, ABAC step by step.

Versions & Dependencies

Laravel Access Control Rules PHP Laravel Model
3.x 8.4+ 13+ RBAC + ABAC
2.x 7.4 - 8.4 8 - 13 RBAC + Dynamic option
1.x 7.1 - 7.3 5.5 - 8 RBAC

Installation

composer require wnikk/laravel-access-rules

For Laravel 12 and older stay on 2.x: composer require wnikk/laravel-access-rules:^2.4.

See the installation page for detailed.

What It Does

This package allows you to manage user permissions and groups (instead roles) in a database.

Once installed you can do stuff like this:

use Wnikk\LaravelAccessRules\Facades\Access;

// Add new rule permission
Access::newRule('articles.edit', 'Access to editing articles');
// Adding permissions to a user
$user->addPermission('articles.edit');

Or you can inherit the rights from another user or groups

// According to the existing user from object
$user->inheritPermissionFrom(User::find(1));

// By identifier
$user->inheritPermissionFrom(User::class, 1);

// From the group
$user->inheritPermissionFrom('Group', 1);

Because all permissions will be registered on Laravel's gate, you can check if a user has a permission with Laravel's default can function:

$user->can('articles.edit'); 

Or without model:

$check = Access::for('AnotherAnySystemUser', 'UserID-From-Any-System-FF01')->can('articles.edit');
if (!$check) {abort(403);}

Examples of how can be used in more detail described in Basic Usage section.

When to choose it, and when not

Choose it when:

  • access depends on data: "orders of my department", "up to my approval limit, but not my own", "clients with a turnover above 1000, except city Y", and the same rule has to filter lists;
  • roles inherit from roles to any depth, or users inherit from users and groups;
  • you need prohibitions on top of roles, and one user has to get back what a role took away;
  • owners of permissions are not only users: roles, groups, teams, API clients, records of another system;
  • every request makes many checks: menus, tables with buttons per row, API resources;
  • an administrator edits access at run time and must not be able to break the application with a typo;
  • a user asks "why can't I see it?" and you need the answer in a minute;
  • you hand policies to an auditor or another system as XACML.

Look elsewhere when:

  • access is a short, fixed list of role names checked in code, and nothing depends on data. A plain role package or Laravel policies alone are less to learn;
  • you are on Laravel 12 or older and need ABAC. Version 3 needs Laravel 13 and PHP 8.4; version 2 is RBAC only.

Alternatives

this package spatie bouncer
Roles and direct permissions yes yes yes
Roles inherit from roles yes, any depth no, roles are flat no
Prohibitions yes, with a five-step priority no yes (forbid)
Owners without a model yes no no
Permission depends on data of the record yes: columns, relations, aggregates, the user, time no, write a policy ownership and single instances
Lists filtered by the same rules, in SQL yes, allowedTo() no no
"Why was it refused?" acr:explain, debug mode no no
Stored rules checked against code acr:lint no no
XACML export and import yes no no
Teams / tenants yes, through inheritance and user.tenant yes, teams yes, scopes

Measured on one machine with the same data (MySQL, 2 000 abilities, the user holds 500 of them, one request of a signed-in user):

this package spatie bouncer
first check of a request 0.2 ms, 0 queries, 51 KB 5.0 ms, 2 queries, 3.9 MB 4.2 ms, 0 queries
next check, permitted 4.0 µs 28.9 µs 4 169 µs
next check, not permitted 4.1 µs 1 461 µs 4 198 µs
a page with 50 checks 0.2 ms 2.5 ms 207 ms

Versions, the method, a smaller data set and what these numbers do not say are in Performance.

Authentication, API tokens and social login belong to other packages. This one decides what a signed-in user may do.

For AI coding agents

The package ships Laravel Boost guidelines and a skill in resources/boost/. php artisan boost:install asks which third-party packages to include: tick wnikk/laravel-access-rules, and Boost adds the guidelines to CLAUDE.md / AGENTS.md of your application and installs the skill access-rules-development. With Boost already installed, run php artisan boost:update --discover. docs/llms.txt is a map of the documentation, and AGENTS.md is for agents that work on the package itself. They tell an agent to check through Gate, to write data-dependent access as a condition instead of a policy plus a hand-written query, to filter lists with allowedTo() and to create rules in migrations.

Opening an Issue

Before opening an issue there are a couple of considerations:

  • You are all awesome!
  • Pull requests are more than welcome.
  • Read the instructions and make sure all steps were followed correctly.
  • Check that the issue is not specific to your development environment setup.
  • Provide duplication steps.
  • Attempt to look into the issue, and if you have a solution, make a pull request.
  • Show that you have made an attempt to look into the issue.
  • Check to see if the issue you are reporting is a duplicate of a previous reported issue.
  • Following these instructions show me that you have tried.
  • Please be considerate that this is an open source project that I provide to the community for FREE when opening an issue.

License

The MIT License (MIT). Please see License File for more information.

Related Packages

artisanpack-ui/rbac

Role-based access control for Laravel — roles with hierarchy, permissions, Blade...

3,176 0
hosseinhezami/laravel-permission-manager

The most advanced enterprise-grade permission management system for Laravel. RBA...

3,445 61
phpzen/laravel-rbac

Role based access control for Laravel 5

3,232 38
spatie/laravel-permission

Permission handling for Laravel 12 and up

117,494,352 12,966
visualappeal/laravel-rbac

Role based access control for Laravel 5

17,639 0