Multi-user Authentication Using Guards in Laravel 5.6

Posted by Jino Antony on 2018-06-18

User authentication in laravel is pretty much easy. Laravel ships with user authentication scaffolding out of the box. But how can we implement a multi user authentication? Let’s look into multi-user authentication using laravel guards.

Let’s start by creating a fresh laravel installation.

composer create-project --prefer-dist laravel/laravel multi-auth

We have 3 types of users.

  1. Admins

  2. Subadmins

  3. Users

Now let’s create the migrations.

Schema::create('admins', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->string('email',100)->unique();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
});

Schema::create('subadmins', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email',100)->unique();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('first_name');
    $table->string('last_name');
    $table->string('email',100)->unique();
    $table->string('phone');
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

If you need to reset passwords then create the “password_resets” table.

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

Now run the migrations.

php artisan migrate

You also need to create models for your tables using the following command.

php artisan make:model YourModelName

Note: For laravel authentication to work, your model must extend Authenticatable.

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    /**
        * The attributes that are mass assignable.
        *
        * [@var](http://twitter.com/var) array
        */
    protected $fillable = [
        'name', 'email', 'password',
    ];
}

To generate authentication scaffolding run the command.

php artisan make:auth

This command will generate the basic views and controllers for authentication.

Now we can configure the guards. You can read more about guards here: https://laravel.com/docs/5.6/authentication#adding-custom-guards

Open config/auth.php and in the guards section add these gurads.

'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'subadmin' => [
            'driver' => 'session',
            'provider' => 'subadmins',
        ],

        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
    ],

Add these providers to the providers section.

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\User::class,
    ],

    'admins' => [
        'driver' => 'eloquent',
        'model' => App\Admin::class,
    ],

    'subadmins' => [
        'driver' => 'eloquent',
        'model' => App\Subadmin::class,
    ],
],

If you have password resets table then add these to the passwords section.

'passwords' => [
    'users' => [
        'provider' => 'users',
        'table' => 'password_resets',
        'expire' => 60,
    ],

    'admins' => [
        'provider' => 'admins',
        'table' => 'password_resets',
        'expire' => 60,
    ],

    'subadmins' => [
        'provider' => 'subadmins',
        'table' => 'password_resets',
        'expire' => 60,
    ],
],

Now you have to replicate the auth controllers for your admin model and subadmin model. Just copy the LoginController located at app/Http/Controllers/Auth directory and rename it to AdminLoginController and SubadminLoginController, then add some methods to the newly created controllers.

AdminLoginController.php

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class AdminLoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = 'admin/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest:admin,admin/home')->except('logout');
}
public function redirectTo()
{
return 'admin/home';
}
protected function guard()
{
return \Auth::guard('admin');
}
public function showLoginForm()
{
return view('auth.adminlogin');
}
}

SubadminLoginController.php

<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class SubadminLoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = 'subadmin/home';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest:subadmin,subadmin/home')->except('logout');
}
public function redirectTo()
{
return 'subadmin/home';
}
protected function guard()
{
return \Auth::guard('subadmin');
}
public function showLoginForm()
{
return view('auth.subadminlogin');
}
}

You have to do the same procedure for RegisterController and ForgotPasswordController.

The middleware used here is guest which is located at app/Http/Middleware/ RedirectIfAuthenticated.php. We need to modify it.

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @param string $redirectTo
* @return mixed
*/
public function handle($request, Closure $next, $guard = null, $redirectTo = '/home')
{
if (Auth::guard($guard)->check()) {
return redirect($redirectTo);
}
return $next($request);
}
}

This middleware help us to redirect the user if authenticated. We can specify the guard and where to redirect by passing those arguments to the middleware.

Now let’s create another middleware for authentication by running the following command.

php artisan make:middleware AssignGuard

<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
class AssignGuard
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @param string $redirectTo
* @return mixed
*/
public function handle($request, Closure $next, $guard = null, $redirectTo = '/login')
{
if (!Auth::guard($guard)->check()) {
return redirect($redirectTo);
}
Auth::shouldUse($guard);
return $next($request);
}
}
view raw AssignGuard.php hosted with ❤ by GitHub

This middleware checks if the user is authenticated or not. If the user is not authenticated he will be redirected to the login page.

In order the middleware to work we need to register it. For that, go to app/Http/Kernel.php and add the following to the $routeMiddleware array.

'assign.guard' => \App\Http\Middleware\AssignGuard::class,

Now we can use the middleware in our routes. Open routes/web.php and add your routes.

<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('admin/login', 'Auth\AdminLoginController@showLoginForm');
Route::post('admin/login', 'Auth\AdminLoginController@login')->name('admin.login');
Route::get('subadmin/login', 'Auth\SubadminLoginController@showLoginForm');
Route::post('subadmin/login', 'Auth\SubadminLoginController@login')->name('subadmin.login');
Route::group(['prefix' => 'admin','middleware' => 'assign.guard:admin,admin/login'],function(){
Route::get('home',function ()
{
return view('adminhome');
});
});
Route::group(['prefix' => 'subadmin','middleware' => 'assign.guard:subadmin,subadmin/login'],function(){
Route::get('home',function ()
{
return view('subadminhome');
});
});
Route::get('/home', 'HomeController@index')->name('home');
view raw web.php hosted with ❤ by GitHub

We also have to replicate the views. Go to resources/views/auth directory and replicate the login views for admin and subadmin. Don’t forget to change the url for login.

That’s it. We have implemented multi-user authentication. You can also add more user levels by adding new guards. The source code is available on github.