DEV Community

Cover image for Laravel Multi Table Authentication
Ikechukwu Vincent
Ikechukwu Vincent

Posted on • Edited on

Laravel Multi Table Authentication

Authentication is an essential component of any web application, and Laravel makes it easy to implement with its built-in authentication features powered by single user table. However what if you have multiple user types, each with its own table in the database? In this scenario, you need to implement multiple table authentication to ensure that the correct user is authenticated and given the right access to the application.

In this article, I will walk you through the steps of implementing multiple table authentication in Laravel, so you can secure your application and give your users the best experience possible. Get ready to dive into the world of Laravel multiple table authentication!

Shall we? Let's go.

I am starting with assumption that you know how to install a fresh laravel application and you have one installed already. That said, let us proceed.

Laravel comes with default users table, lets assume this is the table for default users of your application. And you want another table for admin users.

Model(s)

First we create model for the new class of users in this cas Admins. In your case it could be teachers and students.

php artisan make:model Admin/Admin
Enter fullscreen mode Exit fullscreen mode

Now you have created the Admin model, go in side it and replicate the following code. The Notifiable trait makes it possible to use laravel default notification on these model.

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class Admin extends Authenticatable
{
    use HasFactory, Notifiable;
    protected $guard = 'admin';
}    
Enter fullscreen mode Exit fullscreen mode

Configurations

Laravel have config folder that houses all config files. Inside this file, open auth.php file and paste the following code where we create authentication rules for admin.

In auth.php config

'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
 'admin'=>[
        'driver'=>'eloquent',
        'model'=>App\Models\Admin\Admin::class,
     ],

Enter fullscreen mode Exit fullscreen mode
  'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
        'admin'=>[
           'driver'=>'session',
           'provider'=>'admins',
        ],
    ],

Enter fullscreen mode Exit fullscreen mode
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

        'admins'=>[
            'driver'=>'eloquent',
            'model'=>App\Models\Admin\Admin::class,
         ],
    ],
Enter fullscreen mode Exit fullscreen mode
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
        'admins'=>[
            'driver'=>'eloquent',
            'model'=>App\Models\Admin\Admin::class,
        ],
    ],
Enter fullscreen mode Exit fullscreen mode

Middleware

Now navigate to middlware folder and open the Authentication.php file. This is the file that redirect users who are not authenticated when they try accessing guarded pages. Notice that I commented out the default code in the file.

Middelware Authenticate.php

  // foreach ($guards as $guard) {
        //     if (Auth::guard($guard)->check()) {
        //         return redirect(RouteServiceProvider::HOME);
        //     }
        // }


        foreach ($guards as $guard) {
            if (Auth::guard($guard)->check()) {

                if($guard === 'admin'){
                    return redirect()->route('admin.home');
                }
                return redirect()->route('user.home');
                // return redirect(RouteServiceProvider::HOME);
            }
        }
    if (! $request->expectsJson()) {
            if($request->routeIs('admin.*')){
                return route('admin.login');
            }
            return route('login');
        }
Enter fullscreen mode Exit fullscreen mode

In same middleware folder, open the following file. It is the middleware responsible for redirecting authenticated users based on the guard used in their authentication.

In RedirectIfAuthenticated.php

  // foreach ($guards as $guard) {
        //     if (Auth::guard($guard)->check()) {
        //         return redirect(RouteServiceProvider::HOME);
        //     }
        // }


        foreach ($guards as $guard) {
            if (Auth::guard($guard)->check()) {

                if($guard === 'admin'){
                    return redirect()->route('admin.home');
                }
                return redirect()->route('user.home');
                // return redirect(RouteServiceProvider::HOME);
            }
        }

Enter fullscreen mode Exit fullscreen mode

Admin auth controller

Here we shall create a controller to handle authentication for this category of users.

We begin by creating a controller to handle admin login.

php artisan make:controller Auth/AdminAuthController
Enter fullscreen mode Exit fullscreen mode

Inside the controller

public function __construct()
{
     Auth::setDefaultDriver('admin');
     config(['auth.defaults.passwords' => 'admins']); 
}

public function login()
{
     return view('admin_auth.adminlogin');
}

   public function logoutAdmin(Request $request)
    {
        Auth::guard('admin')->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return redirect('/');
    }

public function store(Request $request)
{
     $request->validate([
         'email'=>'required|string',
         'password'=>'required|min:5|max:30'
      ]);


    if (Auth::guard('admin')->attempt(['email' => $request- 
    >identifier, 'password' => $request->password])|| 
     Auth::guard('admin')->attempt(['username' => $request>identifier, 'password' => $request->password])) {
            // Authentication was successful...
            return redirect()->route('panel');
     }
   else{
       return redirect()->route('admin.login')- 
         >with('fail','Incorrect credentials');
     }
    }

Enter fullscreen mode Exit fullscreen mode

Routes

Now let use create authentication logic for this set of users(admins).

Route::get('/admin/login', [AdminAuthController::class, 'login'])->name('admin.login');
Route::get('/admin/login', [AdminAuthController::class, 'store'])->name('admin.login.store');
Route::post('/admin/logout', [AdminAuthController::class, 'logoutAdmin'])->name('admin.logout');

Enter fullscreen mode Exit fullscreen mode

Pay attention to this part. You will need a route more leading to your dashboard or any other protected pages. Below is exampme of such route. Notice the middleware usage auth:admin. Very important.

Route::get('/panel', [AdminPagesController::class, 'panel_home'])->name('panel')->middleware('auth:admin');
Enter fullscreen mode Exit fullscreen mode

Login html

At this point, let us create blade file or html file for login admin login page. resources\views\admin_auth.blade.php
Take note of where we are submitting this form to.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
  </head>
  <body>
    <!-- <h1>Hello, world!</h1> -->
    <main class="container mt-5">
    <form method="POST" action="{{route('admin.login.store')}}">
        @csrf 
        <div class="form-group">
            <h3 class="text-center">Admin Login</h3>
        </div>
        <div class="mb-3">
            <label for="exampleInputEmail1" class="form-label">Email or Username</label>
            <input type="text" class="form-control" name="identifier" id="exampleInputEmail1" aria-describedby="emailHelp">
            <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
        </div>
        <div class="mb-3">
            <label for="exampleInputPassword1" class="form-label">Password</label>
            <input type="password" name="password" class="form-control" id="exampleInputPassword1">
        </div>
        <div class="mb-3 form-check">
            <input type="checkbox" name="remember" class="form-check-input" id="exampleCheck1">
            <label class="form-check-label" for="exampleCheck1">Check me out</label>
        </div>
        <button type="submit" style="float:right;" class="btn btn-primary">Submit</button>
    </form>
    </main>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Migration

Now let us create table or migration for this new users - admins. Run the command

php artisan make:migration create_admins_table 
Enter fullscreen mode Exit fullscreen mode

Inside the migration file, copy and paste the code below

     $table->string('name');
     $table->string('username')->nullable();
     $table->string('email')->unique();
     $table->timestamp('email_verified_at')->nullable();
     $table->string('password');
     // $table->enum('admin_typ', ['admin'])->nullable();
     $table->rememberToken(); 
Enter fullscreen mode Exit fullscreen mode

Factory and Seeder

Let us now quickly populate the database. We begin by making a model factory for our admin model and also a seeder file.

php artisan make:factory Admin/AdminFactory    
php artisan make:seeder AdminSeeder
Enter fullscreen mode Exit fullscreen mode

Inside the factory Definition method

  return [
            'name' => fake()->name(),
            'username'=>fake()->userName(),
            'email' => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password'=>'$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
Enter fullscreen mode Exit fullscreen mode

Inside the seeder file, in the run method

    \App\Models\Admin\Admin::factory(5)->create();

        \App\Models\Admin\Admin::factory()->create([
            'name' => 'Test Admin',
            'username'=>'admin',
            'email' => 'admin@admin.com',
        ]);
Enter fullscreen mode Exit fullscreen mode

Next run the seeder command to populate your database.

php artisan db:seed --class=AdminSeeder
Enter fullscreen mode Exit fullscreen mode

Remember to create html blade for your protected page.

So that is it. Start your laravel application and try logging in on your admin login page.

I am Vincent Ikechukwu, Full Stack Web Developer and Software Engineer. Connect with me on social media via links below.

If you run into trouble leave a comment or say hi on my social media.

Top comments (0)