How to create a Laravel authentication system for multiple users by using user roles through single form.

Abdullah Hasan Sajjad Rafi
5 min readFeb 27, 2024

--

In this tutorial we will create an authentication system using Laravel which consists of 3 types of users User, Admin and Super Admin. All of them will login in the system by using the same login form and based on their roles they will be redirected to different views and URLs. That’s how they will see different types of functionalities of the website. Only one user model will be used which contains the type of the user’s role.

Super admin will be able to access all the routes on the website and the admin will be able to access only the admin routes and the general user’s routes. General users can access only the general user’s routes.

The source code is given in this repository.

  1. At first Install a fresh Laravel project by running the command line below.
composer create-project laravel/laravel multiUserByRolesSameForm

2. Connect database and run database migrations. For that update the database name in the .env file.

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

Run the command and select yes:

php artisan migrate

3. Install breeze (follow the starter kit): To know more about breeze you can read this (https://laravel.com/docs/10.x/starter-kits#laravel-breeze).

[ use blade and PHPUnit ]

composer require laravel/breeze --dev

php artisan breeze:install

php artisan migrate
npm install
npm run dev

4. Update user migration file using roles. Add this line for role in the user migration file in database\migrations\2014_10_12_000000_create_users_table.php file.

            $table->id();
$table->string('name');
$table->string('email')->unique();
$table->tinyInteger('type')->default(0); //user = 0, admin = 1, super admin = 2
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();

5. Now update the user model file.

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

Run:

php artisan migrate:refresh

6. Create the seeder to create three users. One user, one admin and another one are super admin.

To create the user seeder file run this:

php artisan make:seeder UserSeeder

Put this code in the UserSeeder.php file.

    public function run(): void
{
$userObj = new User();
$userObj->name = 'User Rafi';
$userObj->email = 'userRafi@gmail.com';
$userObj->password = Hash::make('123456789');
$userObj->type = 0;
$userObj->save();

$adminObj = new User();
$adminObj->name = 'Admin Rafi';
$adminObj->email = 'adminRafi@gmail.com';
$adminObj->password = Hash::make('123456789');
$adminObj->type = 1;
$adminObj->save();

$superAdminObj = new User();
$superAdminObj->name = 'Super Admin Rafi';
$superAdminObj->email = 'superAdminRafi@gmail.com';
$superAdminObj->password = Hash::make('123456789');
$superAdminObj->type = 2;
$superAdminObj->save();

}

Import these also in the UserSeeder.php file.

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

Put this code in the DatabaseSeeder.php file.

public function run(): void
{
$this->call([UserSeeder::class]);
// \App\Models\User::factory(10)->create();
// \App\Models\User::factory()->create([
// 'name' => 'Test User',
// 'email' => 'test@example.com',
// ]);
}

Seed the database to create new users.

php artisan db:seed

7. Make the view files. Create the superAdminDashboard.blade.php, adminDashboard.blade.php and the generalUserDashboard.blade.php in views folder.

superAdminDashboard.blade.php :

<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 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 dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __("You're logged in!") }}
<h1>This is Super Admin dashboard!</h1>
</div>
</div>
</div>
</div>
</x-app-layout>

adminDashboard.blade.php :

<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 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 dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __("You're logged in!") }}
<h1>This is Admin dashboard!</h1>
</div>
</div>
</div>
</div>
</x-app-layout>

generalUserDashboard.blade.php :

<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 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 dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __("You're logged in!") }}
<h1>This is General User dashboard!</h1>
</div>
</div>
</div>
</div>
</x-app-layout>

8. Observe the login form. The login form <form method=”POST” action=”{{ route(‘login’) }}”> is sending the request to the ‘login’ route.
So, we need to edit the method that is being called through this route to validate the information of the form.

In the routes\auth.php file the Route::post(‘login’, [AuthenticatedSessionController::class, ‘store’]); line is calling the store method to work with the login form’s submitted information.
So we will create a new method in the AuthenticatedSessionController class to handle the authentication of our form. Before that, create the necessary routes.

9. Create routes in the web.php file into the routes folder.
three routes : /dashboard for general user dashboard, admin/dashboard for admin dashboard and superAdmin/dashboard for super admin dashboard.

/**General user routes **/
Route::middleware(['auth', 'verified'])->get('/dashboard', [DashboardController::class, 'generalUserDashboard'])->name('dashboard');

/**Admin routes **/
Route::middleware('adminAuth')->prefix('admin')->group(function(){
Route::get('/dashboard', [DashboardController::class, 'adminDashboard'])->name('adminDashboardShow');
});

/**Super Admin routes **/
Route::middleware('superAdminAuth')->prefix('superAdmin')->group(function(){
Route::get('/dashboard', [DashboardController::class, 'superAdminDashboard'])->name('superAdminDashboardShow');
});

Comment this portion:

/*
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
*/

10. Create middleware for protecting admin and super admin routes:

The general user’s routes will be protected by ‘auth’ and ‘verified’ middleware.

Run the command to create the middleware.

php artisan make:middleware AdminAuth
php artisan make:middleware SuperAdminAuth

Write this code inside AdminAuth middleware:

    public function handle(Request $request, Closure $next): Response
{
if(Auth()->user()->type == 1 || Auth()->user()->type == 2){ // admin = 1 superAdmin = 2
return $next($request);
}else{
return redirect()->route('login')->with('error', 'You do not have permission to access this page !');
}

}

Write this code inside SuperAdminAuth middleware:

    public function handle(Request $request, Closure $next): Response
{
if(Auth()->user()->type == 2){ // super admin = 2
return $next($request);
}else{
return redirect()->route('login')->with('error', 'You do not have permission to access this page !');
}
}

11. Register the middleware in kernel. Put these lines in the Kernel.php file.

    protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'adminAuth' => \App\Http\Middleware\AdminAuth::class,
'superAdminAuth' => \App\Http\Middleware\SuperAdminAuth::class,

];

12. Create controller. Create a DashboardController.php and for that run this command line:

php artisan make:controller DashboardController

Now write this code inside the DashboardController .

public function superAdminDashboard(){
return view('superAdminDashboard');
}

public function adminDashboard(){
return view('adminDashboard');
}

public function generalUserDashboard(){
return view('generalUserDashboard');
}

13. Update the ‘login’ route.

Update the post route Route::post(‘login’, [AuthenticatedSessionController::class, ‘store’]); of login by this line:

Route::post('login', [AuthenticatedSessionController::class, 'customLogin']);

14. Create a customLogin method inside the AuthenticatedSessionController class which is located in this path :
app\Http\Controllers\Auth\AuthenticatedSessionController.php

Update the code with this method:

    public function customLogin(Request $request){

$input = $request->all();
$this->validate($request, [
'email' => 'required|email',
'password' => 'required',
]);

// check if the given user exists in db
if(Auth::attempt(['email'=> $input['email'], 'password'=> $input['password']])){
// check the user role
if(Auth::user()->type == 0){
return redirect()->route('dashboard');
}
elseif (Auth::user()->type == 1) {
return redirect()->route('adminDashboardShow');
}
elseif (Auth::user()->type == 2) {
return redirect()->route('superAdminDashboardShow');
}
}
else{
return redirect()->route('login')->with('error', "Wrong credentials");
}

}

15. Finally test the authentication by start the Laravel development server. For that run this command line.

php artisan serve

Preview:

--

--