Custom Auth with Multi Guard

version : Laravel 10
Post Time : 16-04-2024

Custom Auth with Multi Guard

Instal Laravel

Run following Commands :

                                      
                                        

composer create-project --prefer-dist laravel/laravel laravel_custom_auth
cd laravel_custom_auth
php artisan migrate

By default a users table will be generated in the database by migration
Create admins table in database like users table

Add Guard in auth.php file
config/auth.php

                                      
                                        

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

'providers' => [
       'users' => [
           'driver' => 'eloquent',
           'model' => App\Models\User::class,
       ],
       'admins' => [
           'driver' => 'eloquent',
           'model' => App\Models\Admin::class,
       ],
       // 'users' => [
       //     'driver' => 'database',
       //     'table' => 'users',
       // ],
   ],

By default User Model already will be there
App/Models/User.php

                                      
                                        

<?php
namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
   use HasApiTokens, HasFactory, Notifiable;

   /**
    * The attributes that are mass assignable.
    *
    * @var array<int, string>
    */
   protected $fillable = [
       'name',
       'email',
       'password',
   ];

   /**
    * The attributes that should be hidden for serialization.
    *
    * @var array<int, string>
    */
   protected $hidden = [
       'password',
       'remember_token',
   ];

   /**
    * The attributes that should be cast.
    *
    * @var array<string, string>
    */
   protected $casts = [
       'email_verified_at' => 'datetime',
   ];
}

Like user model create Admin model

php artisan make:model Admin

App/Models/Admin.php

                                      
                                        

<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class Admin extends Authenticatable
{
   use HasApiTokens, HasFactory, Notifiable;

   /**
    * The attributes that are mass assignable.
    *
    * @var array<int, string>
    */
   protected $fillable = [
       'name',
       'email',
       'password',
   ];

   /**
    * The attributes that should be hidden for serialization.
    *
    * @var array<int, string>
    */
   protected $hidden = [
       'password',
       'remember_token',
   ];

   /**
    * The attributes that should be cast.
    *
    * @var array<string, string>
    */
   protected $casts = [
       'email_verified_at' => 'datetime',
   ];
}

App/Providers/RouteserviceProvider.php

                                      
                                        

<?php
namespace App\Providers;

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
   /**
    * The path to the "home" route for your application.
    *
    * Typically, users are redirected here after authentication.
    *
    * @var string
    */
   public const HOME = '/';
   public const ADMIN_HOME = '/admin/dashboard';

   /**
    * Define your route model bindings, pattern filters, and other route configuration.
    */
   public function boot(): void
   {
       $this->configureRateLimiting();

       $this->routes(function () {
           Route::middleware('api')
               ->prefix('api')
               ->group(base_path('routes/api.php'));

           Route::middleware('web')
               ->group(base_path('routes/web.php'));
       });
   }

   /**
    * Configure the rate limiters for the application.
    */
   protected function configureRateLimiting(): void
   {
       RateLimiter::for('api', function (Request $request) {
           return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
       });
   }
}

app/Http/Middleware/Authenticate.php

                                      
                                        

<?php
namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;

class Authenticate extends Middleware
{
   /**
    * Get the path the user should be redirected to when they are not authenticated.
    */
   protected function redirectTo(Request $request): ?string
   {
       return $request->is('admin/*') ?  route('admin_login') : null;
       return $request->expectsJson() ? null : route('login');
   }
}

app/Http/Middleware/RedirectIfAuthenticated.php

                                      
                                        

<?php
namespace App\Http\Middleware;

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

class RedirectIfAuthenticated
{
   /**
    * Handle an incoming request.
    *
    * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
    */
   public function handle(Request $request, Closure $next, string ...$guards): Response
   {
       $guards = empty($guards) ? [null] : $guards;

       foreach ($guards as $guard) {
           
           if ($guard == 'admin' && Auth::guard($guard)->check()) {
               return redirect(RouteServiceProvider::ADMIN_HOME);
           }

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

       return $next($request);
   }
}

Create LoginController
php artisan make:controller LoginController
app/Http/Controllers/LoginController.php

                                      
                                        

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use DB;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
   public function index(Request $request)
   {
       return view('login');
   }
   public function auth_login(Request $request)
   {
       $request->validate([
           'email'=>'required|email',
           'password'=>'required'
       ]);
       $email = $request->input('email');
       $password = $request->input('password');

       if(Auth::attempt(['email' => $email, 'password' => $password])){
               return redirect()->route('dashboard');
       }else{
           return redirect()->route('login')->with('error', 'Invalid Email Or Password..')->withInput();;
       }
   }
}

create Dashboard Controller
php artisan make:controller DashboardController
app/Http/Controllers/DashboardController.php

                                      
                                        

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class DashboardController extends Controller
{
   public function index(Request $request)
   {   
       return view('dashboard');
   }

   public function logout(Request $request)
   {
       Auth::guard('web')->logout();
       $request->session()->forget('guard.web');
       $request->session()->regenerateToken();
       return redirect()->route('login');
   }
}

Create login view file
app/resources/views/login.blade.php

                                      
                                        

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>User Login Page</title>
  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
  <!-- Main Content -->
  <div class="container">
      <div class="row">
          <div class="col-lg-3 col-md-2"></div>
          <div class="col-lg-6 col-md-8 login-box">
              <div class="col-lg-12 login-key">
                  <i class="fa fa-key" aria-hidden="true"></i>
              </div>
              <div class="col-lg-12 login-title">
                  USER LOGIN
              </div>
              <br>
              <div class="col-lg-12 login-form">
                  <div class="col-lg-12 login-form">
                      <form action="{{ route('auth_login') }}" method="post" id="login-portal-form" class="frm_submit" name="login-portal-form">
                          @csrf
                          @if(Session::has('error'))
                              <h2 style="color:red;">{{ Session::get('error'); }}</h2>
                          @endif
                          <div class="form-group">
                              <label class="form-control-label">USERNAME</label>
                              <input  class="form-control" type="text" name="email" id="email" placeholder="Email" value="{{ old('email') }}">
                              @error('email')
                                  <label class="error" style="color:red">{{ $message }}</label>
                              @enderror
                          </div>
                          <div class="form-group">
                              <label class="form-control-label">PASSWORD</label>
                              <input  class="form-control" type="password" name="password" id="password" placeholder="Password">
                              @error('password')
                              <label class="error" style="color:red">{{ $message }}</label>
                              @enderror
                          </div>
                              <br>
                          <div class="col-lg-12 loginbttm">
                              <div class="col-lg-12 login-btm login-button text-center">
                              <input type="submit" name="submit" class="btn btn-outline-primary" id="submit" value="submit">
                              </div>
                          </div>
                      </form>
                  </div>
              </div>
              <div class="col-lg-3 col-md-2"></div>
          </div>
      </div>
  </div>
</body>
</html>

Create AdminLoginController
php artisan make:controller AdminLoginController
app/Http/Controllers/AdminLoginController.php

                                      
                                        

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Admin;
use DB;
use Illuminate\Support\Facades\Auth;

class AdminLoginController extends Controller
{
   public function index(Request $request)
   {
       return view('admin/login');
   }
   public function auth_admin_login(Request $request)
   {
       $request->validate([
           'email'=>'required|email',
           'password'=>'required'
       ]);
       $email = $request->input('email');
       $password = $request->input('password');

       if (Auth::guard('admin')->attempt(['email' => $email, 'password' => $password])){
               return redirect()->route('admin_dashboard');
       }else{
           return redirect()->route('admin_login')->with('error', 'Invalid Email Or Password..')->withInput();;
       }
   }
}

Create AdminDashboardController
php artisan make:controller AdminDashboardController
app/Http/Controllers/AdminDashboardController.php

                                      
                                        

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class AdminDashboardController extends Controller
{
   public function dashboard(Request $request)
   {   
       return view('admin/dashboard');
   }

   public function logout(Request $request)
   {
       Auth::guard('admin')->logout();
       $request->session()->forget('guard.admin');
       $request->session()->regenerateToken();

       return redirect()->route('admin_login');
   }
}

Create admin login view file
app/resources/views/admin/login.blade.php

                                      
                                        

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Admin Login Page</title>
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
   <!-- Main Content -->
   <div class="container">
       <div class="row">
           <div class="col-lg-3 col-md-2"></div>
           <div class="col-lg-6 col-md-8 login-box">
               <div class="col-lg-12 login-key">
                   <i class="fa fa-key" aria-hidden="true"></i>
               </div>
               <div class="col-lg-12 login-title">
                   ADMIN LOGIN
               </div>
               <br>
               <div class="col-lg-12 login-form">
                   <div class="col-lg-12 login-form">
                       <form action="{{ route('auth_admin_login') }}" method="post" id="login-portal-form" class="frm_submit" name="login-portal-form">
                           @csrf
                           @if(Session::has('error'))
                               <h2 style="color:red;">{{ Session::get('error'); }}</h2>
                           @endif
                           <div class="form-group">
                               <label class="form-control-label">Email</label>
                               <input  class="form-control" type="text" name="email" id="email" placeholder="Email" value="{{ old('email') }}">
                               @error('email')
                                   <label class="error" style="color:red">{{ $message }}</label>
                               @enderror
                           </div>
                           <div class="form-group">
                               <label class="form-control-label">PASSWORD</label>
                               <input  class="form-control" type="password" name="password" id="password" placeholder="Password">
                               @error('password')
                               <label class="error" style="color:red">{{ $message }}</label>
                               @enderror
                           </div>
                               <br>
                           <div class="col-lg-12 loginbttm">
                               <div class="col-lg-12 login-btm login-button text-center">
                               <input type="submit" name="submit" class="btn btn-outline-primary" id="submit" value="submit">
                               </div>
                           </div>
                       </form>
                   </div>
               </div>
               <div class="col-lg-3 col-md-2"></div>
           </div>
       </div>
   </div>
 </body>
</html>

Create dashboard view file
app/resources/views/dashboard.blade.php

                                      
                                        

<!doctype html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>User Dashboard Page</title>
   <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
   <!-- Main Content -->
  <div class="container">
      <div class="row">
          <div class="col-lg-3 col-md-2"></div>
          <div class="col-lg-6 col-md-8 login-box">
              <div class="col-lg-12 login-key">
                  <i class="fa fa-key" aria-hidden="true"></i>
              </div>
              <div class="row">
                  <div class="col-lg-6">
                      USER DASHBOARD
                  </div>
                  <div class="col-lg-6 ">
                      <a href="{{ route('logout') }}">logout</a>
                  </div>
              </div>
              <br>
              <div class="col-lg-12 login-form">
                  <div class="col-lg-12 login-form">
                      {{ Auth::user()->name;}}
                      <br>
                      {{ Auth::user()->email}}
                  </div>
              </div>
              <div class="col-lg-3 col-md-2"></div>
          </div>
      </div>
  </div>
</body>
</html>

Create admin dashboard view file
app/resources/views/admin/dashboard.blade.php

                                      
                                        

<!doctype html>
<html lang="en">
<head>
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>Admin Dashboard Page</title>
   <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
   <!-- Main Content -->
  <div class="container">
      <div class="row">
          <div class="col-lg-3 col-md-2"></div>
          <div class="col-lg-6 col-md-8 login-box">
              <div class="col-lg-12 login-key">
                  <i class="fa fa-key" aria-hidden="true"></i>
              </div>
              <div class="row">
                  <div class="col-lg-6">
                      ADMIN DASHBOARD
                  </div>
                  <div class="col-lg-6 ">
                      <a href="{{ route('admin_logout') }}">logout</a>
                  </div>
              </div>
              <br>
              <div class="col-lg-12 login-form">
                  <div class="col-lg-12 login-form">
                      {{ Auth::user()->name;}}
                      <br>
                      {{ Auth::user()->email}}
                  </div>
              </div>
              <div class="col-lg-3 col-md-2"></div>
          </div>
      </div>
  </div>
</body>
</html>

routes/web.php

                                      
                                        

<?php
use Illuminate\Support\Facades\Route;

use App\Http\Controllers\LoginController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\AdminLoginController;
use App\Http\Controllers\AdminDashboardController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

// Route::get('/', function () {
//     return view('welcome');
// });

/*------Admin Routes-----*/
Route::group(["middleware" => ['guest:admin'],'prefix'=>'admin'],function () {
   Route::get('/', [AdminLoginController::class, 'index'])->name('admin_login');
   Route::post('/auth_admin_login', [AdminLoginController::class, 'auth_admin_login'])->name('auth_admin_login');
});

Route::group(["middleware" => ['auth:admin'],'prefix'=>'admin'],function () {
   Route::get('/dashboard', [AdminDashboardController::class, 'dashboard'])->name('admin_dashboard');
   Route::get('/logout', [AdminDashboardController::class, 'logout'])->name('admin_logout');
});

/*-----User Routes----*/
Route::group(["middleware" => ['guest']],function () {
   Route::get('/login', [LoginController::class, 'index'])->name('login');
   Route::post('/auth_login', [LoginController::class, 'auth_login'])->name('auth_login');   
});

Route::group(["middleware" => ['auth']],function () {
   Route::get('/', [DashboardController::class, 'index'])->name('dashboard');      
   Route::any('/logout', [DashboardController::class, 'logout'])->name('logout'); 
});