Enterprise-grade Attribute-Based Access Control (ABAC) using Policy Group and Action Matrix Strategy for Laravel.
An enterprise-grade, ultra-fast Attribute-Based Access Control (ABAC) authorization engine for Laravel applications built by ExpertApps.
Unlike traditional Role-Based Access Control (RBAC) packages that rely on static database queries, laravel-abac evaluates authorization dynamically using runtime attributes across Subject, Resource, Action, and Environment parameters—executed via an in-memory $O(1)$ Policy Group & Action Matrix Strategy.
In real-world enterprise applications, traditional RBAC (Role-Based Access Control) breaks down as authorization requirements become contextual and dynamic:
1. The "Role Explosion" ProblemIn traditional RBAC, when access depends on conditions (e.g., "Medical Record Viewer in Cardiology during working hours"), developers are forced to invent endless artificial roles like Cardiology_Doctor_WorkingHours_ExportAllowed. This clutters database tables and makes role maintenance unsustainable.
Standard Laravel Policies or RBAC packages evaluate permissions using static database records (User -> Roles -> Permissions). They struggle when permissions depend on real-time runtime parameters, such as:
Standard database-backed permission systems execute N+1 database queries during complex request life cycles just to check permissions across nested models and UI elements.
⚡ Howlaravel-abac Solves Itlaravel-abac shifts authorization from static database lookups to in-memory dynamic evaluation:
[ResourceClass][Action] directly to its target rule chain in constant time.false (access denied), eliminating accidental security loopholes.before): Provides global short-circuit logic (e.g., Super-Admin overrides).Gate::allows(), $this->authorize(), Blade directives, and Artisan generators.| Requirement | Supported Version |
|---|---|
| PHP | ^8.3 |
| Laravel Framework | ^10.0 | ^11.0 | ^12.0 | ^13.0 |
Install the package via Composer:
composer require expertapps/laravel-abac
Publish the package configuration:
php artisan vendor:publish --tag="abac-config"
⚙️ ConfigurationThe published config/abac.php file defines your policy group registry and fallback security behavior:
return [ /* |-------------------------------------------------------------------------- | Registered Policy Groups |-------------------------------------------------------------------------- | List of Policy Groups auto-registered into the AbacRuleRegistry | upon application bootstrap. */ 'policy_groups' => [ App\Abac\Policies\PatientRecordPolicyGroup::class, ], /* |-------------------------------------------------------------------------- | Strict Fail-Closed Policy |-------------------------------------------------------------------------- | When true, any unmapped resource or action evaluates strictly to false. */ 'fail_closed' => true, ];🏁 Get Started Guide
Follow this step-by-step example to build your first ABAC authorization pipeline for a medical PatientRecord resource.
Granular rules implement single-responsibility access logic.
Generate rules using Artisan:
php artisan make:abac-rule DepartmentMatchRule php artisan make:abac-rule WorkingHoursRule php artisan make:abac-rule ExportFeeLimitRule
Rule 1: Check Department Alignment
namespace App\Abac\Rules; use ExpertApps\LaravelAbac\Contracts\AbacRuleInterface; use ExpertApps\LaravelAbac\Domain\AttributeContext; use App\Models\User; use App\Models\PatientRecord; final readonly class DepartmentMatchRule implements AbacRuleInterface { public function supports(AttributeContext $context): bool { return $context->subject instanceof User && $context->resource instanceof PatientRecord; } public function evaluate(AttributeContext $context): bool { /** @var User $user */ $user = $context->subject; /** @var PatientRecord $record */ $record = $context->resource; return $user->department === $record->department; } }
Rule 2: Evaluate Environmental Parameters (Working Hours)
namespace App\Abac\Rules; use ExpertApps\LaravelAbac\Contracts\AbacRuleInterface; use ExpertApps\LaravelAbac\Domain\AttributeContext; final readonly class WorkingHoursRule implements AbacRuleInterface { public function supports(AttributeContext $context): bool { return true; } public function evaluate(AttributeContext $context): bool { $currentHour = (int) date('H'); // Allow access only between 08:00 AM and 06:00 PM return $currentHour >= 8 && $currentHour < 18; } }
Rule 3: Evaluate Dynamic Runtime Attributes
namespace App\Abac\Rules; use ExpertApps\LaravelAbac\Contracts\AbacRuleInterface; use ExpertApps\LaravelAbac\Domain\AttributeContext; final readonly class ExportFeeLimitRule implements AbacRuleInterface { public function supports(AttributeContext $context): bool { return $context->hasAttribute('requested_export_limit'); } public function evaluate(AttributeContext $context): bool { $requestedLimit = $context->getAttribute('requested_export_limit'); // Maximum allowed export threshold is 5000 return $requestedLimit <= 5000; } }Step 2: Create a Policy Group (Action Matrix)
Create a Policy Group to bundle target resources and map actions to rules:
php artisan make:abac-policy-group PatientRecordPolicyGroup
Implement your action matrix:
namespace App\Abac\Policies; use ExpertApps\LaravelAbac\Domain\AbstractPolicyGroup; use ExpertApps\LaravelAbac\Domain\AttributeContext; use App\Models\PatientRecord; use App\Models\User; use App\Abac\Rules\DepartmentMatchRule; use App\Abac\Rules\WorkingHoursRule; use App\Abac\Rules\ExportFeeLimitRule; final class PatientRecordPolicyGroup extends AbstractPolicyGroup { public function targetResource(): string { return PatientRecord::class; } /** * Fast-Pass Hook: Super Admins bypass granular rules immediately. */ public function before(AttributeContext $context): ?bool { if ($context->subject instanceof User && $context->subject->is_super_admin) { return true; } return null; // Continue standard rule evaluation } /** * Action Matrix: Mapping Actions to Required Rules. * All listed rules under an action MUST evaluate to true. */ public function actionRules(): array { return [ 'view' => [ DepartmentMatchRule::class, WorkingHoursRule::class, ], 'export' => [ DepartmentMatchRule::class, WorkingHoursRule::class, ExportFeeLimitRule::class, ], ]; } }Step 3: Register Policy Group in Configuration
Add your Policy Group class to config/abac.php:
return [ 'policy_groups' => [ App\Abac\Policies\PatientRecordPolicyGroup::class, ], 'fail_closed' => true, ];💻 Authorization Usage Methods1. Programmatic Authorization via Facade
use ExpertApps\LaravelAbac\Facades\Abac; use ExpertApps\LaravelAbac\Domain\AttributeContext; $context = AttributeContext::make( subject: auth()->user(), resource: $patientRecord, action: 'export', attributes: [ 'requested_export_limit' => 2500, // Dynamic runtime parameters ] ); if (Abac::isAllowed($context)) { // Perform export action }2. Native Laravel Controllers (
$this->authorize)laravel-abac integrates seamlessly with standard Laravel authorization methods. You can pass dynamic runtime attributes as an array parameter:
namespace App\Http\Controllers; use App\Models\PatientRecord; use Illuminate\Http\Request; class PatientRecordController extends Controller { public function export(Request $request, PatientRecord $record) { // Pass dynamic attributes via standard authorize method $this->authorize('export', [$record, ['requested_export_limit' => $request->input('limit', 1000)] ]); return response()->json(['message' => 'Export successful']); } }3. Native Gate Facade (
Gate::allows)use Illuminate\Support\Facades\Gate; if (Gate::allows('view', [$patientRecord])) { // User is authorized to view }4. Blade Directives
{{-- Simple authorization check --}} @abacAllowed('view', $patientRecord) <button class="btn btn-primary">View Medical Record</button> @else <div class="alert alert-danger">Access Restricted</div> @endabacAllowed {{-- Authorization check with dynamic runtime parameters --}} @abacAllowed('export', $patientRecord, ['requested_export_limit' => 3000]) <a href="{{ route('records.export', $patientRecord) }}">Export Document</a> @endabacAllowed🏛️ Architecture Flow
+------------------+
| AttributeContext | (Subject, Resource, Action, Dynamic Attributes)
+------------------+
|
v
+------------------+
| AbacEngine |
+------------------+
|
v
+------------------+
| AbacRuleRegistry | (O(1) Map Lookup by Resource & Action)
+------------------+
|
v
+-----------------------+
| AbstractPolicyGroup | ---> before() [Fast-Pass Check]
+-----------------------+
|
v
+------------------+
| Action Matrix | ---> Evaluates sequentially mapped AbacRuleInterface instances
+------------------+
|
v
+------------------+
| Decision | ---> Allow (true) / Deny (false)
+------------------+
🔒 Security Modelfalse).before().Run test suites using PHPUnit or Pest:
# Using PHPUnit ./vendor/bin/phpunit # Using Pest PHP ./vendor/bin/pest🛡️ Security & Vulnerabilities
If you discover any security vulnerabilities within laravel-abac, please email mohamed.abdelazim@expertapps.com.sa.
The MIT License (MIT). Please see LICENSE for more information. Developed with ❤️ by ExpertApps.
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | risetechapps/api-key-for-laravel | 0 | 100 | 03-08-2026 |
| 2 | splitstack/invariants | 0 | 24.29 | 03-08-2026 |
| 3 | daite/laravel-procedures | 0 | 19.09 | 03-08-2026 |
| 4 | anjan-talukdar/laravel-gst-invoice | 0 | 19.93 | 03-08-2026 |
| 5 | mitantsoa1/metrics-dash-laravel | 0 | 16.67 | 03-08-2026 |
| 6 | sharpapi/laravel-invoice-manager | 0 | 19.5 | 03-08-2026 |
| 7 | shadman/laravel-skills | 0 | 21.11 | 03-08-2026 |
| 8 | apavliukov/laravel-devtools | 0 | 23.93 | 03-08-2026 |
| 9 | ratts/rih | 0 | 10 | 03-08-2026 |
| 10 | lumnd/platophp | 0 | 17.69 | 03-08-2026 |