What is Role-Based Authentication in Laravel 11?

Role-Based Authentication (RBAC) in Laravel 11 lets you control access and features after login based on a user's role (admin, editor, user, etc.).

Using a single authentication guard, you store a role value in the users table and enforce rules via:

  • Custom middleware — Quick route protection (e.g., 'role:admin')
  • Gates — Simple closure-based checks
  • Policies — Model-specific authorization logic

This lightweight method suits most apps needing tiered access without separate logins. For advanced needs, add Spatie Laravel-Permission. Unlike multi-guard auth (separate logins/tables), RBAC keeps everything unified and simple.



How to Implement Role-Based Authentication in Laravel 11 with Custom Middleware

Table Of Content

1 Prerequisites

  • PHP ≥ 8.2
  • Composer
  • MySQL / preferred DB

2 Introduction

In Laravel 11, implementing role-based authentication is a lightweight and efficient way to control access for different user types—such as User, Editor, and Admin—without the complexity of multiple authentication guards. This approach uses a single web guard combined with a custom middleware that checks a role column in your users table, ensuring secure and role-specific route protection.

Whether you're building a simple CMS, admin panel, or multi-user application, this method provides quick role restrictions while maintaining Laravel's elegant authentication system. For more advanced needs (like granular permissions), you can later integrate packages such as Spatie Laravel-Permission.

In this step-by-step guide, you'll learn how to set up role-based access control in Laravel 11 using custom middleware, including database migration, middleware creation, alias registration in bootstrap/app.php, route protection, and practical testing tips. Perfect for developers seeking a modern, secure solution in 2026.

3 Create a Fresh Laravel 11 Project

3.1 Install Laravel Project For Laravel 11 Custom Middleware

First, make sure your computer has a composer.
Use the following command to install new Laravel Project.

composer create-project laravel/laravel laravel-role-auth

Then, navigate to your project directory:

cd laravel-role-auth

3.2 Configure MySql Database

Upon logging in, the user's record will be stored in the database. This process involves accessing the .env file to input and define the database credentials.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel11
DB_USERNAME=root
DB_PASSWORD=

4 Install Breeze (Blade + auth scaffolding)

Note: laravel/ui is deprecated; for modern Laravel 11, use Breeze:

    
composer require laravel/breeze --dev
php artisan breeze:install blade
npm install && npm run dev    # or npm run build
php artisan migrate   

5 Update User Model and User Migration

Laravel 11 already includes a migration for the User model. In this Laravel 11 custom middleware example, you'll add a role field to the users table for differentiating between user types.

Update Migration File

Now we have to modify migration file Open the file /database/migrations/xxxx_xx_xx_create_users_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->tinyInteger('role')->default(0);
            $table->rememberToken();
            $table->timestamps();
        });

        Schema::create('password_reset_tokens', function (Blueprint $table) {
            $table->string('email')->primary();
            $table->string('token');
            $table->timestamp('created_at')->nullable();
        });

        Schema::create('sessions', function (Blueprint $table) {
            $table->string('id')->primary();
            $table->foreignId('user_id')->nullable()->index();
            $table->string('ip_address', 45)->nullable();
            $table->text('user_agent')->nullable();
            $table->longText('payload');
            $table->integer('last_activity')->index();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('users');
        Schema::dropIfExists('password_reset_tokens');
        Schema::dropIfExists('sessions');
    }
};
?>

Now we need to run command below to create table in database

php artisan migrate

Modify User Model File

Open the file /app/Models/User.php

<?php
namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    protected $fillable = [
        'name',
        'email',
        'password',
        'role',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }

    // Optional helper method
    public function isAdmin(): bool
    {
        return $this->role === 'admin';
    }

    public function isEditor(): bool
    {
        return $this->role === 'editor';
    }
}
?>

6 Create custom Role middleware

Create the Laravel 11 Custom Middleware to handle user roles. In the terminal, run:

php artisan make:middleware Role

The command will generate a file under directory /app/Http/Middleware/Role.php

Implement Logic in Middleware

We have to add new parameter '$role' to validate User role requested from web.php, we will implement if the role is match will allow to the next request, otherwise will redirect to home page open the file /app/Http/Middleware/Role.php

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class Role
{
    public function handle(Request $request, Closure $next, string $role): Response
    {
        if (!Auth::check()) {
            return redirect()->route('login');
        }

        if (Auth::user()->role !== $role) {
            return redirect()->route('dashboard')
                ->with('error', 'You do not have permission to access this page.');
        }

        return $next($request);
    }
}

?>

7 Register the Middleware - bootstrap/app.php

To use your Laravel 11 custom middleware, you need to register it in your application.
Laravel 11 introduces significant changes to middleware handling. In previous versions, you could register middleware in the Kernel.php file. However, with Laravel 11, you must define middleware in the bootstrap/app.php file.
Open the file bootstrap/app.php Add inside ->withMiddleware(...):

<?php
namespace App\Http\Controllers\Auth;
uuse Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
        $middleware->alias([
            'role' => \App\Http\Middleware\Role::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

?>

8 Modify Controller - HomeController and LoginController

In this step, we are going to use default home controller and add method userHome(), managerHome(), and adminHome() open the file /app/Http/Controllers/HomeController.php

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller
{
    public function index()
    {
        return redirect()->route('dashboard');
    }
}
?>

9 Define a Route

Define routes for Laravel 11 multiple authentications with the newly created middleware in web.php:
routes/web.php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\HomeController;  // We'll create this

Route::get('/', function () {
    return view('welcome');
});

Route::get('/dashboard', function () {
    $msg = match (auth()->user()->role) {
        'admin'  => 'Welcome, Administrator! You have full access.',
        'editor' => 'Hello Editor! You can edit content.',
        'user'   => 'Hi User! Enjoy browsing.',
        default  => 'Welcome!',
    };

    return view('dashboard', compact('msg'));
})->middleware(['auth', 'verified'])->name('dashboard');

// Role-specific dashboards (optional - or keep everything in /dashboard)
Route::middleware(['auth', 'role:editor'])->group(function () {
    Route::get('/editor', fn() => view('dashboard', ['msg' => 'Editor Area']))->name('editor');
});

Route::middleware(['auth', 'role:admin'])->group(function () {
    Route::get('/admin', fn() => view('dashboard', ['msg' => 'Admin Panel']))->name('admin');
});

require __DIR__.'/auth.php';

10 Update Home Blade File

Modify home blade to display username and role
resources/views/dashboard.blade.php


   <x-app-layout>
    <x-slot name="header">
        <h2 class="font-semibold text-xl text-gray-800 leading-tight">
            Dashboard
        </h2>
    </x-slot>

    <div class="py-12">
        <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
            <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                <div class="p-6 text-gray-900">
                    {{ $msg ?? 'Welcome to your dashboard!' }}

                    <p class="mt-4">
                        Your role: <strong>{{ auth()->user()->role }}</strong>
                    </p>

                    @if (session('error'))
                        <div class="mt-4 p-4 bg-red-100 text-red-700 rounded">
                            {{ session('error') }}
                        </div>
                    @endif
                </div>
            </div>
        </div>
    </div>
</x-app-layout>

11 Add Seeder for Testing

Now create a seeder "UserRoleSeeder"
Use the following artisan command to Create Controller.

php artisan make:seeder UserRoleSeeder

database/seeders/UserRoleSeeder.php

<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\User;
use Illuminate\Support\Facades\Hash;

class UserRoleSeeder extends Seeder
{
    public function run(): void
    {
        User::create([
            'name' => 'Regular User',
            'email' => 'user@example.com',
            'password' => Hash::make('password'),
            'role' => 'user',
        ]);

        User::create([
            'name' => 'Content Editor',
            'email' => 'editor@example.com',
            'password' => Hash::make('password'),
            'role' => 'editor',
        ]);

        User::create([
            'name' => 'Administrator',
            'email' => 'admin@example.com',
            'password' => Hash::make('password'),
            'role' => 'admin',
        ]);
    }
}
?>

Use the following artisan command to run seeder.

php artisan db:seed --class=UserRoleSeeder

12 Folder Structure

13 Run Laravel Server to Test the App

Use the following artisan command to Test the App.

php artisan serve

Testing

  • Go to /register or /login → create/login with any account (or use seeder ones)
  • After login → /dashboard shows role message
  • Try /admin → only admin can access, others get redirected with error
  • Same for /editor

14 Conclusion

This is a fully working Laravel 11 role-based system using custom middleware. For true multiple authentication (separate admin table, separate login pages/guards), let me know — it's more involved (config/auth.php guards, separate models, custom logins).
Revathi M - PHP and CodeIgniter Developer

Written by Revathi M

PHP Developer & Technical Writer · 10+ years building web applications with CodeIgniter and Laravel

Revathi specializes in PHP backend development, authentication systems, and REST API design. She writes practical, production-tested tutorials at Get Sample Code to help developers build secure applications faster.

Frequently Asked Questions

No, it uses the default single 'web' guard with role checks in middleware. Separate guards (e.g., admin) are not implemented.

In the controller (e.g., HomeController), create methods like userHome() or adminHome() and return role-specific views or messages.

Create a seeder to insert users with different role values (0,1,2), then login as each to test protected routes.

Common issues: Incorrect role value in database, middleware not registered properly in bootstrap/app.php, or missing 'auth' middleware before role check.

The tutorial implements role-based authentication using a single 'web' guard. Roles (user, manager, admin) are stored in a 'role' column on the users table and checked via custom middleware.

You need PHP 8.2+, Composer, MySQL database configured in .env, and Laravel UI for authentication scaffolding (composer require laravel/ui).

Update the users migration to add $table->tinyInteger('role')->default(0); then run php artisan migrate. Roles: 0=user, 1=manager, 2=admin (cast to strings in User model).

Run php artisan make:middleware UserRoleMiddleware. In handle(), check if Auth::user()->role matches the passed parameter, else redirect.

In bootstrap/app.php, use ->withMiddleware() to alias 'role' to your UserRoleMiddleware class.

Use middleware('role:user') (or 'role:admin') on route groups after 'auth' middleware to restrict access based on user role.