Multi-auth in Laravel 11 (with Inertia and React | session driver)

Ali
4 min readJun 9, 2024

--

Introduction

Let’s familiarize ourselves very briefly with what is multi-auth in Laravel. At this point you already know how the authentication system works in Laravel. When you use one of the starter kits for Laravel Breeze (I chose Inertia and React); out of thebox you will get a session based authentication system. The gives you the ability to use authentication on userstable (the User model).

Now let’s say you want to have another type of user, say Admin. You don’t want to use the same users table for Admin because they have different fields and different roles. This is where multi-auth comes in. It lets you have multiple authentication systems in your Laravel application without repeating the logic. Usually this refers to as having multiple guards.

Steps

Step 1: Create a new guard

First thing you need to do is create a new guard. You can do this by editing the config/auth.php file. Add a new guard

'guards' => [
//

// our new guard
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],

// ..

'provider' => [
// ..

// our new provider (the model on which the guard will be based)
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],

// ..
],

// ..

'passwords' => [
// ..

// our new password reset token table (will use the password_resets table for password reset tokens)
'admins' => [
'provider' => 'admins',
'table' => 'password_reset_tokens',
'expire' => 60,
'throttle' => 60,
],
],
],

Step 2: Create a new model and migration

Create a new model and migration for the Admin user. You can do this by running the following command

php artisan make:model Admin -m

The migration can look something like this

// .. 
Schema::create('admins', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
// ..

Use Authenticatable trait in the Admin model, so that we can hook into Laravel’s authentication system.

use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
// ..
}

Step 3: Create new routes for the admin

Create new routes for the admin. You can add this into web.php in the routes directory.

use Illuminate\Support\Facades\Route;

// Guest routes for the admin
Route::middleware('guest')
->prefix('admin')
->group(function () {
// /admin/login [GET]
Route::get('/login', function () {
return Inertia::render('Admin/Login'); // shows the login page (duplicate the login page from the user)
})->name('admin.login');

// /admin/login [POST]
Route::post('/login', [AdminLoginController::class, 'login']); // handles the login and redirects to the dashboard

// /admin/register [GET]
Route::get('/register', function () {
return Inertia::render('Admin/Register'); // shows the register page (duplicate the register page from the user)
})->name('admin.register');

// /admin/register [POST]
Route::post('/register', [AdminRegisterController::class, 'register']); // handles the registration and redirects to the dashboard

// /admin/logout [POST]
Route::post('/logout', [AdminLogoutController::class, 'logout']); // handles the logout and redirects to the login page [See redirection below to set it up correctly]
});

// Protected routes for the admin (/admin/dashboard) [GET]
Route::middleware('auth:admin')
->prefix('admin')
->group(function () {
Route::get('/dashboard', function () {
return Inertia::render('Admin/Dashboard');
})->name('admin.dashboard');
});

When you did set it up correctly, using /admin/register POST request should create a new Admin user in the database in the admins table.

Step 4: Set up redirection

When you enter /admin you want to be redirected to /admin/login if you are not logged in. This simple route can be added to the web.php file to do just that:

// ..
Route::get('/admin', fn () => redirect(route('admin.login')));
// ..

When you log out you should be redirected to /admin/login, for this you need to do a little setup in bootstrap/app.php file.

// ..

->withMiddleware(function (Middleware $middleware) {

// ..

$middleware->redirectGuestsTo(function () {
if (str_starts_with(request()->path(), 'admin')) {
return route('login.admin');
}

return route('login');
});


// ..
})


// ..

In Laravel 11 the file structure is a bit different. You can find the app.php file in the bootstrap directory. More on this in the Laravel 11 release notes.

So when we log out as an admin we are unauthenticated which Laravel can detect and offers us a method in that case where we can execute our redirection logic inside the redirectGuestsTo method.

On the flip side, if we are logged in and are on /admin/dashboard page; and then enter /admin/login we should be redirected to /admin/dashboard. This can be done by adding a guest middleware for the admin and use it for the login and register.

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class RedirectAdminIfAuthenticated
{
public function handle(Request $request, Closure $next)
{
$adminUser = auth('admin')->user() ?? null; // check if the admin user is logged in

if ($adminUser) {
return redirect()->route('dashboard.admin');
}

return $next($request);
}
}

One little bonus elegance you do is to set an alias for your middleware in the bootstrap/app.php file.

// ..

->withMiddleware(function (Middleware $middleware) {

// ..

$middleware->alias([
'guest.admin' => \App\Domain\Admin\Middleware\RedirectAdminIfAuthenticated::class,
]);


// ..
})


// ..

Now you can use the guest.admin middleware with the alias in the web.php file like so:

// ..

Route::middleware('guest.admin') // use the guest.admin middleware
->prefix('admin')
->group(function () {

// ..

});

And that’s it! You have a multi-auth system in Laravel 11 with Inertia.js and React. You can now have multiple types of users in your application.

If you have any questions or feedback, feel free to reach out to me on Twitter.

Also checkout: https://www.youtube.com/watch?v=iKyGbvQwhWs

--

--

Responses (1)