Kritim Yantra
Jun 01, 2025
Implementing a robust roles and permissions system is a critical requirement for most web applications. Laravel provides excellent built-in tools for authorization, and when combined with Backpack for Laravel (a popular admin panel solution), you can create a powerful administrative interface with minimal effort.
In this comprehensive guide, we'll walk through setting up roles and permissions in Laravel 12 using the Backpack admin panel. We'll cover installation, configuration, CRUD interfaces for roles and permissions, and how to implement authorization throughout your application.
Before we begin, ensure you have:
First, let's install Backpack for Laravel:
composer require backpack/crud
Then, publish the necessary files:
php artisan backpack:install
This will install Backpack and set up the basic admin panel structure.
For roles and permissions, we'll use the popular spatie/laravel-permission
package:
composer require spatie/laravel-permission
Publish the migration and config file:
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
Run the migrations:
php artisan migrate
Update your User model to use the HasRoles
trait:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// ... rest of your model code
}
Now, let's create CRUD interfaces for managing roles and permissions.
Generate a Permission CRUD:
php artisan backpack:crud permission
Update the generated PermissionCrudController
:
<?php
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use Spatie\Permission\Models\Permission;
class PermissionCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
public function setup()
{
CRUD::setModel(Permission::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/permission');
CRUD::setEntityNameStrings('permission', 'permissions');
}
protected function setupListOperation()
{
CRUD::column('id');
CRUD::column('name')->label('Permission Name');
CRUD::column('guard_name');
CRUD::column('created_at');
CRUD::column('updated_at');
}
protected function setupCreateOperation()
{
CRUD::setValidation([
'name' => 'required|min:2|max:255|unique:permissions,name',
'guard_name' => 'required|min:2|max:255',
]);
CRUD::field('name')->label('Permission Name');
CRUD::field('guard_name')->default('web');
}
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}
Generate a Role CRUD:
php artisan backpack:crud role
Update the generated RoleCrudController
:
<?php
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class RoleCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
public function setup()
{
CRUD::setModel(Role::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/role');
CRUD::setEntityNameStrings('role', 'roles');
}
protected function setupListOperation()
{
CRUD::column('id');
CRUD::column('name')->label('Role Name');
CRUD::column('guard_name');
CRUD::column('permissions')->label('Permissions')
->type('relationship_count')
->suffix(' permissions');
CRUD::column('created_at');
CRUD::column('updated_at');
}
protected function setupCreateOperation()
{
CRUD::setValidation([
'name' => 'required|min:2|max:255|unique:roles,name',
'guard_name' => 'required|min:2|max:255',
]);
CRUD::field('name')->label('Role Name');
CRUD::field('guard_name')->default('web');
CRUD::field('permissions')
->label('Permissions')
->type('select2_multiple')
->entity('permissions')
->model(Permission::class)
->attribute('name')
->pivot(true);
}
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}
Generate a User CRUD if you don't have one:
php artisan backpack:crud user
Update the UserCrudController
to include role management:
<?php
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use App\Models\User;
use Spatie\Permission\Models\Role;
class UserCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
public function setup()
{
CRUD::setModel(User::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/user');
CRUD::setEntityNameStrings('user', 'users');
}
protected function setupListOperation()
{
CRUD::column('id');
CRUD::column('name');
CRUD::column('email');
CRUD::column('roles')
->label('Roles')
->type('relationship_count')
->suffix(' roles');
CRUD::column('created_at');
CRUD::column('updated_at');
}
protected function setupCreateOperation()
{
CRUD::setValidation([
'name' => 'required|min:2|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:6',
]);
CRUD::field('name');
CRUD::field('email');
CRUD::field('password')->type('password');
CRUD::field('roles')
->label('Roles')
->type('select2_multiple')
->entity('roles')
->model(Role::class)
->attribute('name')
->pivot(true);
}
protected function setupUpdateOperation()
{
CRUD::setValidation([
'name' => 'required|min:2|max:255',
'email' => 'required|email|unique:users,email,'.CRUD::getCurrentEntryId(),
'password' => 'nullable|min:6',
]);
CRUD::field('name');
CRUD::field('email');
CRUD::field('password')->type('password');
CRUD::field('roles')
->label('Roles')
->type('select2_multiple')
->entity('roles')
->model(Role::class)
->attribute('name')
->pivot(true);
}
}
Add the new CRUDs to the Backpack menu. Open app/Providers/AppServiceProvider.php
and update the boot()
method:
use Backpack\MenuCRUD\app\Models\MenuItem;
public function boot()
{
// Create default menu items
if (MenuItem::count() === 0) {
MenuItem::create([
'name' => 'Dashboard',
'type' => 'link',
'link' => backpack_url('dashboard'),
'icon' => 'la la-home',
]);
MenuItem::create([
'name' => 'Users',
'type' => 'link',
'link' => backpack_url('user'),
'icon' => 'la la-user',
]);
MenuItem::create([
'name' => 'Roles',
'type' => 'link',
'link' => backpack_url('role'),
'icon' => 'la la-id-badge',
]);
MenuItem::create([
'name' => 'Permissions',
'type' => 'link',
'link' => backpack_url('permission'),
'icon' => 'la la-key',
]);
}
}
To ensure only authorized users can access the admin panel, update the Backpack configuration. In config/backpack/base.php
:
'middleware_class' => [
App\Http\Middleware\CheckIfAdmin::class,
\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Cookie\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Spatie\Permission\Middlewares\PermissionMiddleware::class,
],
Create a new middleware to check for admin access:
php artisan make:middleware CheckIfAdmin
Update the CheckIfAdmin
middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckIfAdmin
{
public function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()->hasRole('admin')) {
return $next($request);
}
abort(403, 'Unauthorized access');
}
}
Register the middleware in bootstrap/app.php
:
->withMiddleware(function ($middleware) {
$middleware->alias([
'admin' => \App\Http\Middleware\CheckIfAdmin::class,
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
]);
})
Create a seeder for initial roles and permissions:
php artisan make:seeder RolesAndPermissionsSeeder
Update the seeder:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use App\Models\User;
class RolesAndPermissionsSeeder extends Seeder
{
public function run()
{
// Reset cached roles and permissions
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
// Create permissions
$permissions = [
'user_management_access',
'permission_create',
'permission_edit',
'permission_show',
'permission_delete',
'permission_access',
'role_create',
'role_edit',
'role_show',
'role_delete',
'role_access',
'user_create',
'user_edit',
'user_show',
'user_delete',
'user_access',
];
foreach ($permissions as $permission) {
Permission::create(['name' => $permission]);
}
// Create roles and assign created permissions
$role = Role::create(['name' => 'admin']);
$role->givePermissionTo(Permission::all());
$role = Role::create(['name' => 'user']);
$role->givePermissionTo(['user_show']);
// Create admin user
$user = User::create([
'name' => 'Admin',
'email' => 'admin@example.com',
'password' => bcrypt('password'),
]);
$user->assignRole('admin');
// Create regular user
$user = User::create([
'name' => 'User',
'email' => 'user@example.com',
'password' => bcrypt('password'),
]);
$user->assignRole('user');
}
}
Run the seeder:
php artisan db:seed --class=RolesAndPermissionsSeeder
Now that we have our roles and permissions system set up, let's see how to use it in your application.
public function index()
{
// Only users with 'user_access' permission can access this
$this->authorize('user_access');
// Or check for a role
if (!auth()->user()->hasRole('admin')) {
abort(403);
}
// Your controller logic
}
@can('user_create')
<a href="{{ route('users.create') }}">Create New User</a>
@endcan
@role('admin')
<p>This is only visible to admin users</p>
@endrole
Route::group(['middleware' => ['role:admin']], function () {
Route::resource('users', UserController::class);
});
Route::group(['middleware' => ['permission:user_access']], function () {
Route::get('/dashboard', 'DashboardController@index');
});
You can customize which operations are available based on permissions. For example, in your CRUD controllers:
protected function setupListOperation()
{
if (!backpack_user()->can('user_access')) {
abort(403);
}
// ... rest of your setup
}
protected function setupCreateOperation()
{
if (!backpack_user()->can('user_create')) {
abort(403);
}
// ... rest of your setup
}
You can create a custom operation to manage user roles and permissions more granularly. First, create a new operation:
php artisan backpack:operation AssignRolesAndPermissions
Then implement it in your UserCrudController:
use \App\Http\Controllers\Operations\AssignRolesAndPermissionsOperation;
// ...
public function setupAssignRolesAndPermissionsOperation()
{
CRUD::set('entity', 'user');
// Add fields for roles and permissions
CRUD::field('roles')
->label('Roles')
->type('select2_multiple')
->entity('roles')
->model(Role::class)
->attribute('name')
->pivot(true);
CRUD::field('permissions')
->label('Direct Permissions')
->type('select2_multiple')
->entity('permissions')
->model(Permission::class)
->attribute('name')
->pivot(true);
}
It's crucial to test your roles and permissions system:
In this guide, we've created a comprehensive roles and permissions system in Laravel 12 using Backpack for the admin panel. We've:
This setup provides a solid foundation for managing access control in your Laravel application. You can extend it further by:
Remember to always follow the principle of least privilege when assigning permissions and regularly review your access control setup to ensure it remains secure as your application evolves.
Transform from beginner to Laravel expert with our personalized Coaching Class starting June 13, 2025. Limited enrollment ensures focused attention.
1-hour personalized coaching
Build portfolio applications
Industry-standard techniques
Interview prep & job guidance
Complete your application to secure your spot
Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google