Upgrade & Secure Your Future with DevOps, SRE, DevSecOps, MLOps!

We spend hours scrolling social media and waste money on things we forget, but won’t spend 30 minutes a day earning certifications that can change our lives.
Master in DevOps, SRE, DevSecOps & MLOps by DevOps School!

Learn from Guru Rajesh Kumar and double your salary in just one year.


Get Started Now!

A Complete Guide to Laravel 12 RBAC

Uncategorized

A Complete Guide to Laravel 12 RBAC: From Setup to Landing Page

Welcome! This guide will walk you through building a complete Laravel 12 application with a robust Role-Based Access Control (RBAC) system. We’ll set up authentication and create three distinct user roles: Admin, Editor, and User. By the end, you’ll have a secure application with role-specific dashboards, a professional landing page, and the knowledge to troubleshoot common setup issues in modern Laravel.

Let’s get started.

Step 1: Set Up Your Laravel 12 Project

First, let’s create a fresh Laravel project. Open your terminal and run the following Composer command:

bashcomposer create-project --prefer-dist laravel/laravel laravel-rbac

Once the project is created, navigate into the directory:

bashcd laravel-rbac

Next, configure your database. Open the .env file in the root of your project and update the DB_ variables with your local database credentials.

textDB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_rbac
DB_USERNAME=root
DB_PASSWORD=

Step 2: Add Authentication Scaffolding

Laravel makes it easy to set up login and registration systems. We’ll use the laravel/ui package with Bootstrap.

bashcomposer require laravel/ui
php artisan ui bootstrap --auth
npm install
npm run dev

These commands generate all the necessary authentication views, routes, and controllers. Keep the npm run dev process running in a terminal to compile your assets as you work.

Step 3: Implement Role-Based Access Control (RBAC)

Now, let’s build the core of our RBAC system. We’ll add a role column to our users table to manage permissions.

Create the Migration

Generate a migration to add the role column:

bashphp artisan make:migration add_role_to_users_table --table=users

Open the new migration file in database/migrations/ and modify the up method to add the column. We’ll set ‘user’ as the default role.

php// ...
public function up(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('role')->default('user'); // Default role is 'user'
    });
}
// ...

Run the migration to update your database schema:

bashphp artisan migrate

Create the Role Middleware

Middleware is perfect for protecting routes. Let’s create one to check a user’s role.

bashphp artisan make:middleware RoleMiddleware

This creates app/Http/Middleware/RoleMiddleware.php. Open it and update the handle method to check if the authenticated user has the required role.

php<?php

namespace App\Http\Middleware;

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

class RoleMiddleware
{
    public function handle(Request $request, Closure $next, $role): Response
    {
        if (Auth::check() && Auth::user()->role == $role) {
            return $next($request);
        }

        return redirect('/home')->with('error', 'You do not have permission to access this page.');
    }
}

Register the Middleware (The Laravel 12 Way)

In Laravel 11 and 12, middleware aliases are no longer registered in app/Http/Kernel.php. Instead, you register them in bootstrap/app.php.

Open bootstrap/app.php and add your middleware alias inside the withMiddleware() method.

php<?php

use 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) {
        // Register your 'role' middleware alias here
        $middleware->alias([
            'role' => \App\Http\Middleware\RoleMiddleware::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        // ...
    })->create();

This is a critical step. Forgetting it will cause a Target class [role] does not exist error.

Step 4: Define Role-Specific Routes

With the middleware registered, you can now protect routes in routes/web.php. We’ll create separate dashboard routes for each role.

phpuse Illuminate\Support\Facades\Route;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\LandingPageController;

// Landing Page
Route::get('/', [LandingPageController::class, 'index']);

Auth::routes();

// Home redirector
Route::get('/home', [HomeController::class, 'index'])->name('home');

// Admin Routes
Route::middleware(['auth', 'role:admin'])->group(function () {
    Route::get('/admin/dashboard', function () {
        return view('admin.dashboard');
    })->name('admin.dashboard');
});

// Editor Routes
Route::middleware(['auth', 'role:editor'])->group(function () {
    Route::get('/editor/dashboard', function () {
        return view('editor.dashboard');
    })->name('editor.dashboard');
});

// User Routes
Route::middleware(['auth', 'role:user'])->group(function () {
    Route::get('/user/dashboard', function () {
        return view('user.dashboard');
    })->name('user.dashboard');
});

Step 5: Set Up Controllers and Views

Modify the RegisterController

Update the RegisterController at app/Http/Controllers/Auth/RegisterController.php to ensure new users are automatically assigned the ‘user’ role.

php// ... in RegisterController.php
use App\Models\User;
use Illuminate\Support\Facades\Hash;

protected function create(array $data)
{
    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
        'role' => 'user', // Automatically assign 'user' role
    ]);
}

Modify the HomeController

The HomeController will act as a router after login, redirecting users to the correct dashboard based on their role. Open app/Http/Controllers/HomeController.php and update the index method.

php// ... in HomeController.php
use Illuminate\Support\Facades\Auth;

public function index()
{
    $role = Auth::user()->role;

    if ($role == 'admin') {
        return redirect()->route('admin.dashboard');
    } elseif ($role == 'editor') {
        return redirect()->route('editor.dashboard');
    } else {
        return redirect()->route('user.dashboard');
    }
}

Create the Dashboard Views

Create the following Blade files for each role’s dashboard.

Admin Dashboard (resources/views/admin/dashboard.blade.php):

xml@extends('layouts.app')
@section('content')
<div class="container">
    <div class="card">
        <div class="card-header">{{ __('Admin Dashboard') }}</div>
        <div class="card-body">Welcome, Admin! You have full control.</div>
    </div>
</div>
@endsection

Editor Dashboard (resources/views/editor/dashboard.blade.php):

xml@extends('layouts.app')
@section('content')
<div class="container">
    <div class="card">
        <div class="card-header">{{ __('Editor Dashboard') }}</div>
        <div class="card-body">Welcome, Editor! You can manage content.</div>
    </div>
</div>
@endsection

User Dashboard (resources/views/user/dashboard.blade.php):

xml@extends('layouts.app')
@section('content')
<div class="container">
    <div class="card">
        <div class="card-header">{{ __('User Dashboard') }}</div>
        <div class="card-body">Welcome, User! This is your personal space.</div>
    </div>
</div>
@endsection

Step 6: Build a Professional Landing Page

A great application needs a welcoming landing page. Let’s create one using Tailwind CSS for modern styling.

Create the Controller

bashphp artisan make:controller LandingPageController

Add an index method to app/Http/Controllers/LandingPageController.php:

phppublic function index()
{
    return view('welcome');
}

Create the Blade View

Replace the content of resources/views/welcome.blade.php with the following code. It includes a hero section, features, and a footer.

xml<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Laravel RBAC Starter</title>
    <link rel="preconnect" href="https://fonts.bunny.net">
    <link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600,700" rel="stylesheet" />
    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
</head>
<body class="bg-gray-50 text-gray-800 antialiased">
    <div class="relative min-h-screen flex flex-col items-center justify-center">
        <!-- Header -->
        <header class="w-full max-w-7xl mx-auto px-6 lg:px-8 absolute top-0 pt-6">
            @if (Route::has('login'))
                <nav class="flex items-center justify-end gap-4">
                    @auth
                        <a href="{{ url('/home') }}" class="rounded-md px-3 py-2 text-black ring-1 ring-transparent transition hover:text-black/70 focus:outline-none focus-visible:ring-[#FF2D20]">Dashboard</a>
                    @else
                        <a href="{{ route('login') }}" class="rounded-md px-3 py-2 text-black ring-1 ring-transparent transition hover:text-black/70 focus:outline-none focus-visible:ring-[#FF2D20]">Log in</a>
                        @if (Route::has('register'))
                            <a href="{{ route('register') }}" class="rounded-md px-3 py-2 text-black ring-1 ring-transparent transition hover:text-black/70 focus:outline-none focus-visible:ring-[#FF2D20]">Register</a>
                        @endif
                    @endauth
                </nav>
            @endif
        </header>

        <!-- Main Content -->
        <main class="w-full max-w-7xl mx-auto px-6 lg:px-8 text-center py-20">
            <h1 class="text-4xl font-bold tracking-tight text-gray-900 sm:text-6xl">Your App with Role-Based Access</h1>
            <p class="mt-6 text-lg leading-8 text-gray-600">A robust starting point for your next Laravel project, complete with authentication and pre-configured user roles.</p>
            <div class="mt-10 flex items-center justify-center gap-x-6">
                <a href="{{ route('register') }}" class="rounded-md bg-indigo-600 px-4 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">Get Started</a>
                <a href="#features" class="text-sm font-semibold leading-6 text-gray-900">Learn more <span aria-hidden="true">→</span></a>
            </div>
        </main>
        
        <!-- Footer -->
        <footer class="w-full text-center py-8 text-sm text-gray-500">
            <p>Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }})</p>
        </footer>
    </div>
</body>
</html>

Note: This landing page assumes you have Tailwind CSS installed. If you used laravel/ui bootstrap, the styling might differ. You can install Tailwind by following the official Laravel documentation.

Step 7: Testing and Final Touches

To test your roles, you’ll need to manually update a user’s role in the database.

  1. Register a new user (they will have the ‘user’ role).
  2. Use a database client like phpMyAdmin or Sequel Ace to change their role in the users table to admin or editor.
  3. Log in as that user. You should be redirected to the correct dashboard.

Congratulations! You now have a fully functional Laravel 12 application with authentication and a multi-tiered RBAC system. This starter project is the perfect foundation for building complex, secure web applications.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x