Laravel 12 Roles and Permissions with Admin Panel Backpack: A Complete Guide

Author

Kritim Yantra

Jun 01, 2025

Laravel 12 Roles and Permissions with Admin Panel Backpack: A Complete Guide

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.

Prerequisites

Before we begin, ensure you have:

  • Laravel 12 installed
  • Composer installed
  • Basic knowledge of Laravel
  • MySQL or another database system

Step 1: Install Laravel Backpack

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.

Step 2: Install Spatie Laravel-Permission

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

Step 3: Configure User Model

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
}

Step 4: Create Backpack CRUDs for Roles and Permissions

Now, let's create CRUD interfaces for managing roles and permissions.

Create Permission CRUD

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();
    }
}

Create Role CRUD

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();
    }
}

Create User CRUD with Role Assignment

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);
    }
}

Step 5: Add Menu Items to Admin Panel

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',
        ]);
    }
}

Step 6: Protect Backpack Routes with Middleware

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,
    ]);
})

Step 7: Seed Initial Roles and Permissions

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

Step 8: Implement Authorization in Your Application

Now that we have our roles and permissions system set up, let's see how to use it in your application.

In Controllers

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
}

In Blade Views

@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

In Routes

Route::group(['middleware' => ['role:admin']], function () {
    Route::resource('users', UserController::class);
});

Route::group(['middleware' => ['permission:user_access']], function () {
    Route::get('/dashboard', 'DashboardController@index');
});

Step 9: Customizing the Admin Panel

Add Permission Checks to Backpack Operations

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
}

Create a Custom Operation for Assigning Roles and Permissions

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);
}

Step 10: Testing Your Implementation

It's crucial to test your roles and permissions system:

  1. Try logging in as the admin user and verify you can access all sections
  2. Log in as a regular user and verify access restrictions
  3. Test creating new roles and assigning permissions
  4. Verify that permission checks work in controllers, views, and routes

Conclusion

In this guide, we've created a comprehensive roles and permissions system in Laravel 12 using Backpack for the admin panel. We've:

  1. Installed and configured Backpack and Spatie's laravel-permission package
  2. Created CRUD interfaces for users, roles, and permissions
  3. Implemented middleware to protect routes
  4. Seeded initial data
  5. Shown how to use authorization throughout your application
  6. Added customizations to enhance the admin panel

This setup provides a solid foundation for managing access control in your Laravel application. You can extend it further by:

  • Adding more granular permissions
  • Implementing permission groups
  • Creating a more sophisticated user interface for permission management
  • Adding audit logging for permission changes

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.

LIVE MENTORSHIP ONLY 5 SPOTS

Laravel Mastery
Coaching Class Program

KritiMyantra

Transform from beginner to Laravel expert with our personalized Coaching Class starting June 13, 2025. Limited enrollment ensures focused attention.

Daily Sessions

1-hour personalized coaching

Real Projects

Build portfolio applications

Best Practices

Industry-standard techniques

Career Support

Interview prep & job guidance

Total Investment
$200
Duration
30 hours
1h/day

Enrollment Closes In

Days
Hours
Minutes
Seconds
Spots Available 5 of 10 remaining
Next cohort starts:
June 13, 2025

Join the Program

Complete your application to secure your spot

Application Submitted!

Thank you for your interest in our Laravel mentorship program. We'll contact you within 24 hours with next steps.

What happens next?

  • Confirmation email with program details
  • WhatsApp message from our team
  • Onboarding call to discuss your goals

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts