PHPackages                             amrshah/laravel-arbac - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. amrshah/laravel-arbac

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

amrshah/laravel-arbac
=====================

:Enterprise level Attribute/Role base access control package for Laravel

041PHP

Since Sep 18Pushed 4mo agoCompare

[ Source](https://github.com/amrshah/laravel-arbac)[ Packagist](https://packagist.org/packages/amrshah/laravel-arbac)[ RSS](/packages/amrshah-laravel-arbac/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (2)Used By (1)

Laravel ARBAC – Advanced Role &amp; Attribute-Based Access Control
==================================================================

[](#laravel-arbac--advanced-role--attribute-based-access-control)

[![Tests](https://github.com/amrshah/arbac/actions/workflows/run-tests.yml/badge.svg)](https://github.com/amrshah/arbac/actions)[![Latest Version on Packagist](https://camo.githubusercontent.com/889f7a26f662560c9719f89cd371e281cd1d8b976e1be5a032b1ed8a06aa4934/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616d72736861682f6c61726176656c2d61726261632e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/amrshah/laravel-arbac)[![Total Downloads](https://camo.githubusercontent.com/6e17d0df38019b90477618674edcdebeaeb6823128dfd0675c43621b7c8af5d6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f616d72736861682f6c61726176656c2d61726261632e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/amrshah/laravel-arbac)

> **ARBAC** is a production-ready Laravel package that combines classic Role-Based Access Control (RBAC) with Attribute-Based Access Control (ABAC) and enterprise features — while remaining simple enough for small projects.

---

Features
--------

[](#features)

- ✅ **RBAC** - Traditional role-based permissions (built on [spatie/laravel-permission](https://github.com/spatie/laravel-permission))
- ✅ **ABAC** - Attribute-based access control with custom rules
- ✅ **Multi-Tenancy** - Tenant-aware permissions out of the box
- ✅ **High Performance** - Built-in caching for permission checks
- ✅ **Audit Logging** - Track all permission checks for compliance
- ✅ **Middleware** - Protect routes with ease
- ✅ **Blade Directives** - Control view rendering
- ✅ **Time-Based Permissions** - Restrict access by time/date
- ✅ **IP-Based Permissions** - Whitelist/blacklist IPs
- ✅ **Hierarchical Roles** - Role inheritance support
- ✅ **Permission Groups** - Bulk assign permissions
- ✅ **Laravel 10 &amp; 11** - Full support for modern Laravel
- ✅ **PHP 8.1+** - Modern PHP features

---

Installation
------------

[](#installation)

```
composer require amrshah/laravel-arbac
```

### Local Development

[](#local-development)

If you're developing locally with a path repository:

```
// composer.json
"repositories": [
  {
    "type": "path",
    "url": "packages/amrshah/arbac"
  }
]
```

Then:

```
composer require amrshah/laravel-arbac:dev-main
```

### Configuration

[](#configuration)

Publish the config and migrations:

```
php artisan vendor:publish --tag="arbac-config"
php artisan vendor:publish --tag="arbac-migrations"
php artisan migrate
```

This creates `config/arbac.php` where you can configure models, cache, multi-tenancy, audit logging, and more.

---

Quick Start
-----------

[](#quick-start)

### Basic RBAC

[](#basic-rbac)

```
use Amrshah\Arbac\Facades\Arbac;

// Assign role to user
Arbac::assignRole($user, 'editor');

// Check permission
if (Arbac::check($user, 'edit posts')) {
    // User can edit posts
}

// Remove role
Arbac::removeRole($user, 'editor');
```

### Attribute-Based Rules

[](#attribute-based-rules)

Create custom rules for complex authorization logic:

```
php artisan arbac:make-rule PostOwnerRule
```

This creates a rule class in `app/Arbac/Rules/PostOwnerRule.php`:

```
namespace App\Arbac\Rules;

use Amrshah\Arbac\Contracts\AttributeRuleInterface;
use Illuminate\Contracts\Auth\Authenticatable;

class PostOwnerRule implements AttributeRuleInterface
{
    public function supports(string $permission): bool
    {
        return $permission === 'edit post';
    }

    public function check(Authenticatable $user, string $permission, array $context = []): bool
    {
        $post = $context['post'] ?? null;
        return $post && $post->user_id === $user->id;
    }
}
```

Register in `config/arbac.php`:

```
'attribute_rules' => [
    \App\Arbac\Rules\PostOwnerRule::class,
],
```

Use it:

```
// User can edit their own posts even without explicit permission
Arbac::check($user, 'edit post', ['post' => $post]);
```

---

Important: Cache Invalidation
-----------------------------

[](#important-cache-invalidation)

ARBAC caches permission checks for performance. **Cache is automatically invalidated** when roles or permissions change:

```
// Automatic invalidation (enabled by default)
$user->assignRole('editor');        // ✅ Cache invalidated
$role->givePermissionTo('edit');    // ✅ Cache invalidated
$permission->update([...]);         // ✅ Cache invalidated
```

**Disable automatic invalidation:**

```
// config/arbac.php
'cache' => [
    'auto_invalidate' => false, // Manual invalidation only
],
```

**Warning:** Direct database updates bypass observers and require manual cache flush:

```
// Direct DB update - cache NOT invalidated
DB::table('model_has_roles')->insert([...]);

// Manual flush required
Arbac::flushUserPermissions($user);
// or
Arbac::flushAllCache();
```

**Optional: Add to User Model**

```
use Amrshah\Arbac\Traits\InvalidatesArbacCache;

class User extends Authenticatable
{
    use InvalidatesArbacCache; // Auto-invalidate on user changes
}
```

---

Middleware
----------

[](#middleware)

### Basic Middleware

[](#basic-middleware)

Protect routes with ARBAC middleware:

```
// routes/web.php
Route::put('/posts/{post}', [PostController::class, 'update'])
    ->middleware('arbac:edit post');

Route::get('/admin', [AdminController::class, 'index'])
    ->middleware('role:admin');
```

### IP-Restricted Routes

[](#ip-restricted-routes)

Protect routes by IP address:

```
// config/arbac.php
'ip_whitelist' => ['192.168.1.0/24', '10.0.0.1'],

// routes/web.php
Route::get('/admin', [AdminController::class, 'index'])
    ->middleware('arbac.ip:ip-restricted.admin');

// Custom IP list
Route::get('/secure', [SecureController::class, 'index'])
    ->middleware('arbac.ip:ip-restricted.secure,custom.secure_ips');
```

**Environment Configuration:**

```
ARBAC_IP_WHITELIST=192.168.1.0/24,10.0.0.1
```

### ⏰ Time-Restricted Routes

[](#-time-restricted-routes)

Restrict access by time window:

```
// config/arbac.php
'time_window' => [
    'start_time' => '09:00',
    'end_time' => '17:00',
    'timezone' => 'America/New_York',
],

// routes/web.php
Route::get('/business-hours', [Controller::class, 'index'])
    ->middleware('arbac.time:time-restricted.access');

// Custom time window
Route::get('/special', [Controller::class, 'index'])
    ->middleware('arbac.time:time-restricted.special,custom.special_hours');
```

**Environment Configuration:**

```
ARBAC_TIME_START=09:00
ARBAC_TIME_END=17:00
ARBAC_TIMEZONE=America/New_York
```

### 🔧 Context-Aware Middleware

[](#-context-aware-middleware)

Pass context from config or request:

```
// With config-based context
Route::post('/api/resource', [ApiController::class, 'store'])
    ->middleware('arbac.context:create resource,api.resource_context');

// Context from request (default)
Route::post('/posts', [PostController::class, 'store'])
    ->middleware('arbac.context:create post');
```

---

Blade Directives
----------------

[](#blade-directives)

Control what users see in your views:

```
@arbac('edit post', ['post' => $post])
    Edit Post
@endarbac

@hasrole('admin')
    Admin Panel
@endhasrole

@haspermission('users.create')
    Create User
@endhaspermission

@unlessrole('guest')
    Welcome back!
@endunlessrole
```

---

Multi-Tenancy
-------------

[](#multi-tenancy)

### What ARBAC Provides

[](#what-arbac-provides)

ARBAC is **tenant-aware**, not a full tenant isolation framework:

✅ **What ARBAC Does:**

- Automatically adds `tenant_id` to permission checks
- Provides `scopeTenant()` for queries
- Caches are tenant-scoped
- Audit logs are tenant-scoped

❌ **What ARBAC Does NOT Do:**

- Enforce tenant isolation at database level
- Prevent cross-tenant data access
- Manage user-tenant relationships

### Configuration

[](#configuration-1)

Enable in `config/arbac.php`:

```
'multi_tenancy' => [
    'enabled' => true,
    'bypass_roles' => ['super_admin'], // Roles that bypass tenant checks
],
```

### Usage

[](#usage)

Permissions are automatically scoped to the current tenant:

```
tenancy()->initialize($tenant);

$user->givePermissionTo('edit posts'); // Scoped to current tenant

Arbac::check($user, 'edit posts'); // Checks within tenant context
```

### Super Admin Bypass

[](#super-admin-bypass)

**✅ SAFE - Role-based bypass:**

```
// config/arbac.php
'multi_tenancy' => [
    'bypass_roles' => ['super_admin', 'global_admin'],
],

// Super admins automatically bypass tenant checks
$superAdmin->assignRole('super_admin');
Arbac::check($superAdmin, 'edit posts'); // No tenant_id required
```

**❌ DANGEROUS - Do NOT toggle config per request:**

```
// ❌ DON'T DO THIS (leaks in Octane/Swoole)
if ($user->hasRole('super_admin')) {
    config(['arbac.multi_tenancy.enabled' => false]);
}
```

### Your Responsibilities

[](#your-responsibilities)

1. **Add `tenant_id` to your models**
2. **Use `scopeTenant()` in queries**
3. **Implement tenant switching logic**
4. **Enforce isolation at application level**

### Best Practices

[](#best-practices)

```
// ✅ GOOD - Explicit tenant scoping
$posts = Post::tenant()->where('user_id', $user->id)->get();

// ❌ BAD - No tenant scope
$posts = Post::where('user_id', $user->id)->get(); // May leak across tenants
```

---

Caching
-------

[](#caching)

ARBAC caches permission checks for optimal performance:

```
// config/arbac.php
'cache' => [
    'enabled' => true,
    'auto_invalidate' => true, // Automatic cache invalidation (recommended)
    'store'   => 'redis', // or 'default'
    'ttl'     => 3600,    // seconds
],
```

**Automatic Invalidation (Enabled by Default):**Cache is automatically cleared when roles/permissions change. See the [Cache Invalidation](#%EF%B8%8F-important-cache-invalidation) section above for details.

**Manual Cache Management:**

```
$manager = app(ArbacManager::class);
$manager->flushUserPermissions($user);
$manager->flushAllCache();
```

---

Audit Logging
-------------

[](#audit-logging)

Track all permission checks for compliance and debugging:

```
// config/arbac.php
'audit' => [
    'enabled'     => true,
    'log_granted' => true,
    'log_denied'  => true,
],
```

### ⚠️ Performance Impact

[](#️-performance-impact)

**Warning:** Audit logging adds **10-20ms per permission check** (synchronous write).

**For high-traffic applications:**

1. **Log denied only:**

```
'audit' => [
    'log_granted' => false,
    'log_denied' => true,
],
```

2. **Use async logging (custom implementation):**

```
// Extend ArbacManager
protected function logPermissionCheck(...$args): void
{
    dispatch(new LogPermissionCheck(...$args));
}
```

### Query Audit Logs

[](#query-audit-logs)

```
use Amrshah\Arbac\Models\ArbacAuditLog;

// Get all denied access attempts
$deniedLogs = ArbacAuditLog::denied()->get();

// Get logs for specific user
$userLogs = ArbacAuditLog::forUser($user)->get();

// Get logs for specific permission
$permissionLogs = ArbacAuditLog::forPermission('edit posts')->get();

// Tenant-scoped logs
$tenantLogs = ArbacAuditLog::tenant()->get();
```

---

Time-Based Permissions
----------------------

[](#time-based-permissions)

Restrict access by time windows:

```
use Amrshah\Arbac\Rules\TimeBasedRule;

// Register in config
'attribute_rules' => [
    \Amrshah\Arbac\Rules\TimeBasedRule::class,
],

// Check permission with time constraints
Arbac::check($user, 'time-restricted.access', [
    'start_time' => '09:00',
    'end_time'   => '17:00',
    'timezone'   => 'America/New_York',
]);
```

---

IP-Based Permissions
--------------------

[](#ip-based-permissions)

Whitelist IPs for sensitive operations:

```
use Amrshah\Arbac\Rules\IpWhitelistRule;

// Register in config
'attribute_rules' => [
    \Amrshah\Arbac\Rules\IpWhitelistRule::class,
],

// Check permission with IP whitelist
Arbac::check($user, 'ip-restricted.admin', [
    'allowed_ips' => ['192.168.1.100', '10.0.0.0/24'], // Supports CIDR
]);
```

---

Hierarchical Roles
------------------

[](#hierarchical-roles)

### Non-Transitive (Default)

[](#non-transitive-default)

Define role inheritance in `config/arbac.php`:

```
'role_hierarchy' => [
    'admin' => ['manager', 'member'],
    'manager' => ['member'],
],
```

Use in your User model:

```
use Amrshah\Arbac\Traits\HasRoleHierarchy;

class User extends Authenticatable
{
    use HasRoleHierarchy;
}

// Check if user has role or higher
if ($user->hasRoleOrHigher('manager')) {
    // User is manager or admin
}
```

**⚠️ Important:** `hasRoleOrHigher()` is **one-level only**, not transitive.

### Transitive (Optional)

[](#transitive-optional)

For deep hierarchies, use the `HasTransitiveRoleHierarchy` trait:

```
use Amrshah\Arbac\Traits\HasTransitiveRoleHierarchy;

class User extends Authenticatable
{
    use HasTransitiveRoleHierarchy;
}

// Config
'role_hierarchy' => [
    'super_admin' => ['admin'],
    'admin' => ['manager'],
    'manager' => ['member'],
],

// Now supports transitive checks
$user->hasRoleOrHigherTransitive('member'); // Walks full hierarchy tree
```

---

Permission Groups
-----------------

[](#permission-groups)

Bulk manage permissions:

```
use Amrshah\Arbac\Models\PermissionGroup;

$adminGroup = PermissionGroup::create([
    'name'        => 'admin_permissions',
    'description' => 'All admin permissions',
    'permissions' => ['users.*', 'roles.*', 'permissions.*'],
]);

// Assign all permissions to a role
$adminGroup->assignToRole($adminRole);

// Remove all permissions from a role
$adminGroup->removeFromRole($adminRole);
```

---

🧪 Testing
---------

[](#-testing)

```
composer test
composer test:coverage
```

---

Documentation
-------------

[](#documentation)

- [Installation Guide](docs/installation.md)
- [Configuration](docs/configuration.md)
- [Creating Rules](docs/creating-rules.md)
- [Multi-Tenancy](docs/multi-tenancy.md)
- [Performance](docs/performance.md)
- [API Reference](docs/api-reference.md)

---

Contributing
------------

[](#contributing)

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.

---

Security
--------

[](#security)

If you discover any security-related issues, please email  instead of using the issue tracker.

---

License
-------

[](#license)

MIT © Ali Raza (Amr Shah)

---

Credits
-------

[](#credits)

- Built on top of [spatie/laravel-permission](https://github.com/spatie/laravel-permission)
- Inspired by enterprise authorization systems
- Made with ❤️ for the Laravel community

###  Health Score

20

—

LowBetter than 14% of packages

Maintenance52

Moderate activity, may be stable

Popularity3

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity15

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/90f157c51295d6bdcd833529eef62bcba7502ad24fb320678e8183bde3c01f40?d=identicon)[amrshah](/maintainers/amrshah)

---

Top Contributors

[![amrshah](https://avatars.githubusercontent.com/u/1771447?v=4)](https://github.com/amrshah "amrshah (20 commits)")

### Embed Badge

![Health badge](/badges/amrshah-laravel-arbac/health.svg)

```
[![Health](https://phpackages.com/badges/amrshah-laravel-arbac/health.svg)](https://phpackages.com/packages/amrshah-laravel-arbac)
```

###  Alternatives

[namshi/jose

JSON Object Signing and Encryption library for PHP.

1.8k99.6M101](/packages/namshi-jose)[league/oauth1-client

OAuth 1.0 Client Library

99698.8M106](/packages/league-oauth1-client)[bezhansalleh/filament-shield

Filament support for `spatie/laravel-permission`.

2.8k2.9M88](/packages/bezhansalleh-filament-shield)[gesdinet/jwt-refresh-token-bundle

Implements a refresh token system over Json Web Tokens in Symfony

70516.4M35](/packages/gesdinet-jwt-refresh-token-bundle)[league/oauth2-google

Google OAuth 2.0 Client Provider for The PHP League OAuth2-Client

41721.2M118](/packages/league-oauth2-google)[illuminate/auth

The Illuminate Auth package.

9327.3M1.0k](/packages/illuminate-auth)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
