orchestra/authorization
Orchestra Authorization adds role- and permission-based access control to Laravel apps on the Orchestra platform. Define roles, attach permissions, and gate routes, menus, and UI elements per user with simple APIs for checking and managing access.
composer.json for PHP and illuminate/* constraints before installing. Do not assume Laravel 8+ support from the release note.composer require orchestra/authorization:^5.0
php artisan vendor:publish --provider="Orchestra\Authorization\AuthorizationServiceProvider"
php artisan migrate
Verify the actual provider name and publish tags from the package source or README; release notes do not document them.composer.json — PHP/Laravel constraints.config/authorization.php (after publishing) — table names, models, guards, cache settings.src/ — service provider, contracts, role/permission models, and any Gate integration.database/migrations/ — role, permission, and pivot tables.admin and editor; permission posts.publish; admin receives it; editor does not. Then verify with Gate::allows('posts.publish'), @can('posts.publish'), and the can:posts.publish route middleware.Treat the first integration as a spike: prove install, migration, seeding, assignment, and enforcement end to end before designing around the package.
Centralize permission names. Define permission strings as constants or a PHP enum rather than scattering raw strings through controllers and views. Typo'd abilities fail silently as denials, which is hard to debug.
Use seeders as the source of truth for roles and permissions. Make seeders idempotent with firstOrCreate/updateOrCreate, and run them in every environment. Avoid manual database edits for role definitions; they will drift between environments.
Layer coarse and fine-grained checks.
Gate::before for a deliberate super-admin bypass, and Gate::after only for logging or non-security adjustments.Enforce at the boundaries. Use can: middleware on routes, $this->authorize() in controllers, Gate::allows() in services, and @can in Blade. Avoid scattering raw role-name checks like $user->hasRole('admin') through business logic; prefer ability checks so role composition can change later.
Bridge package permissions into Laravel's Gate. If the package does not automatically register abilities, define them in a service provider:
Gate::before(function ($user, $ability) {
return $user->hasRole('super-admin') ? true : null;
});
Keep the bypass narrow, auditable, and tested. Returning false from Gate::before would deny everything, so return null when not applicable.
Model the role assignment lifecycle explicitly. Decide whether users can hold multiple roles, whether roles are global or scoped, and what happens when a role is deleted. Write tests for role removal and permission changes, not just grants.
Cache carefully. Permission lookups are frequent. Cache per user per request, or use the package's cache if provided. Invalidate or version the cache when roles or permissions change. Avoid caching authorization decisions across requests without a clear invalidation strategy.
Handle non-web contexts. Queued jobs, console commands, and scheduled tasks have no authenticated user. Pass the acting user or authorization context explicitly, or re-authorize inside the job. Do not rely on ambient auth state.
Scope by guard or tenant if needed. If the application has multiple guards or tenants, confirm how the package resolves the current user and whether roles are shared or isolated. If multi-tenancy is unsupported, isolate role assignments at the application layer rather than assuming the package handles it.
Test authorization as a first-class concern. Seed a known role matrix in tests, use actingAs, and assert both allowed and denied paths. Include tests for super-admin bypass, missing roles, deleted roles, and permission changes.
php artisan config:clear, route:clear, and view:clear. In production, ensure config:cache includes the package config and that the provider is not excluded by dont-discover.false, not an exception. Use constants and add tests for every permission used in routes and views.Gate::before returning true for a role bypasses all policies, including future ones. Restrict it to a dedicated role, log its use, and test that ordinary users cannot acquire it accidentally.Gate::inspect($ability) to get a Response with a message, and log denied checks in non-production or during investigation. Check the authenticated user, resolved guard, role assignments, and whether the ability is registered at all.Gate::before/Gate::after, and package config. Confirm the actual contracts and events before building on them.How can I help you explore Laravel packages today?