How to Implement Multiple Authentication Guards in Laravel 9 - TechvBlogs

How to Implement Multiple Authentication Guards in Laravel 9

Learn How to Implement Multiple Authentication Guards in Laravel 9 in this step-by-step guide.


Suresh Ramani - Author - TechvBlogs
Suresh Ramani
 

1 year ago

TechvBlogs - Google News

Eventually, we are going to learn how to create multiple auth (Authentication) in Laravel using guards, and we will also consider other laravel imperatives that are useful to build laravel basic auth app from starting.

In general, Authentication is the security process, and it indicates acknowledging the genuine user with proper account details.

We will develop two users one is an admin, and the other one is a regular user. Based on their roles, we will allow them to access in the app using middleware. Let us begin our work and start building our application.

How to Implement Multiple Authentication Guards in Laravel 9

Before starting the development, let us first see the video on how multi-guard authentication works. In our demo, we used two logins, one for the blogger and one for the admin.

Step 1: Install Laravel Project

First, open Terminal and run the following command to create a fresh laravel project:

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

or, if you have installed the Laravel Installer as a global composer dependency:

laravel new multi-guard-auth

Step 2: Install Laravel UI

Next, you need to run the below command in your terminal

composer require laravel/ui

Step 3: Setup Auth Scaffolding with Bootstrap 5

php artisan ui bootstrap --auth

 Step 4: Install NPM Dependencies

Run the following command to install frontend dependencies:

npm install

After the Update Of Laravel 9.20.0, Laravel replaces Webpack with Vite. You can follow this article for Setup Bootstrap 5 in Laravel 9.

Step 5. Configure Database Details:

After, Installation Go to the project root directory, open the .env file, and set database detail as follow:

DB_CONNECTION=mysql 
DB_HOST=127.0.0.1 
DB_PORT=3306 
DB_DATABASE=<DATABASE NAME>
DB_USERNAME=<DATABASE USERNAME>
DB_PASSWORD=<DATABASE PASSWORD>

Step 6: Create Migration and Model

Use the below command to create migration and Model for Admin and Blog

php artisan make:model Admin -m

-m the argument is used to create a migration file.

Update the migration file of the admin like the users’ migration table, or you can also extend the table by adding fields needed for the application.

Step 7: Define Guards

Guards define how the admin is authenticated for each request. Our application will have a guard Admin. after defining the guards set their providers. When we use these guards it tells what to use for authentication or validation. Open the Admin.php file in the app/Models folder. Update guard as admin and fillable array with field names.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Model;

class Admin extends Authenticatable
{
    use HasFactory;

    protected $guard = "admin";

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

    protected $hidden = [
        'password',
        'remember_token',
    ];
}

Open config/auth.php for adding guard. We’ve added one guard: admin and updated their provider’s array.

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session"
    |
    */

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

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model/table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

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

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that each reset token will be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

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

    /*
    |--------------------------------------------------------------------------
    | Password Confirmation Timeout
    |--------------------------------------------------------------------------
    |
    | Here you may define the number of seconds before a password confirmation
    | times out and the user is prompted to re-enter their password via the
    | confirmation screen. By default, the timeout lasts for three hours.
    |
    */

    'password_timeout' => 10800,

];

Step 8: Set Up Controller

Open the LoginController in app/Http/Controllers/Auth and edit as follows:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController 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 = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
        $this->middleware('guest:admin')->except('logout');
    }
}

We set the middleware to restrict access to this controller or its methods. It is important we defined all the different types of guests in the controller. This way, if one type of user is logged in and you try to use another user type to log in, it will redirect you to a predefined authentication page.

Now, define the login for admins:

app/Http/Controllers/Auth/LoginController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;


class LoginController 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 = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
        $this->middleware('guest:admin')->except('logout');
    }

    public function showAdminLoginForm()
    {
        return view('auth.login', ['url' => route('admin.login-view'), 'title'=>'Admin']);
    }

    public function adminLogin(Request $request)
    {
        $this->validate($request, [
            'email'   => 'required|email',
            'password' => 'required|min:6'
        ]);

        if (\Auth::guard('admin')->attempt($request->only(['email','password']), $request->get('remember'))){
            return redirect()->intended('/admin/dashboard');
        }

        return back()->withInput($request->only('email', 'remember'));
    }
}

We have set up a method to return the login page for an admin. We will use the same page for all the user types and only change the URL they get sent to. Saves us a lot of code we could avoid writing.

We also defined the adminLogin the method which checks that the right credentials are supplied. Then we attempt to log a user in with the admin guard. It is important we set this guard when attempting a login so that the Auth facade will check the right table matching credentials. It will also set up our authentication so we can restrict pages based on the type of user who is logged in.

Step 9: Modify RegisterController

Open the RegisterController and edit as follows:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
        $this->middleware('guest:admin');
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\Models\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
}

We have set up the middleware the controller will use, just like we did with the LoginController.

Now, let us set up the methods to return the registration pages for the admin:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
        $this->middleware('guest:admin');
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\Models\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }

    public function showAdminRegisterForm()
    {
        return view('auth.register', ['route' => route('admin.register-view'), 'title'=>'Admin']);
    }
}

Now, we can define our methods for creating an admin:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use App\Models\Admin;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;



class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
        $this->middleware('guest:admin');
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\Models\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }

    public function showAdminRegisterForm()
    {
        return view('auth.register', ['route' => route('admin.register-view'), 'title'=>'Admin']);
    }

    protected function createAdmin(Request $request)
    {
        $this->validator($request->all())->validate();
        $admin = Admin::create([
            'name' => $request['name'],
            'email' => $request['email'],
            'password' => Hash::make($request['password']),
        ]);
        return redirect()->intended('admin');
    }
}

Step 10: Set up authentication pages

Open the resources/views/auth/login.blade.php file and edit as follows:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ $title ?? "" }} {{ __('Login') }}</div>

                <div class="card-body">
                    @isset($route)
                        <form method="POST" action="{{ $route }}">
                    @else
                        <form method="POST" action="{{ route('login') }}">
                    @endisset
                    
                        @csrf

                        <div class="row mb-3">
                            <label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <div class="col-md-6 offset-md-4">
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>

                                    <label class="form-check-label" for="remember">
                                        {{ __('Remember Me') }}
                                    </label>
                                </div>
                            </div>
                        </div>

                        <div class="row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Login') }}
                                </button>

                                @if (Route::has('password.request'))
                                    <a class="btn btn-link" href="{{ route('password.request') }}">
                                        {{ __('Forgot Your Password?') }}
                                    </a>
                                @endif
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

We are checking if we passed a route parameter to the page when we called it. If we did, we modify the form's action to use the route parameter. We also modified the header of the form so that it shows the type of user based on their login parameter.

Open the resources/views/auth/register.blade.php file and edit as follows:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ $title ?? "" }} {{ __('Register') }}</div>

                <div class="card-body">
                    @isset($route)
                        <form method="POST" action="{{ $route }}">
                    @else
                        <form method="POST" action="{{ route('register') }}">
                    @endisset
                        @csrf

                        <div class="row mb-3">
                            <label for="name" class="col-md-4 col-form-label text-md-end">{{ __('Name') }}</label>

                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus>

                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label for="email" class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email">

                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label for="password" class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label for="password-confirm" class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>

                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
                            </div>
                        </div>

                        <div class="row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Register') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

We replicated what we did for the login page here.

Step 11: Create the pages for authenticated users

Now that we are done setting up the login and register page, let us make the page the admin will see when they are authenticated. Open the terminal and run the following commands to create a new file. Next, we will insert the corresponding code snippets into the files.

touch resources/views/admin.blade.php

Next, insert this code block into the resources/views/admin.blade.php file:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif

                    Hello Admin!
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Finally, open the resources/views/home.blade.php file and replace with the following:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Dashboard') }}</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif

                    Hello User!
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Step 12: Set up the routes

Let us define the routes to access all the pages we have created so far. Open the routes/web.php file and replace with the following:

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| 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!
|
*/

use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\Auth\RegisterController;

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

Auth::routes();

Route::get('/admin',[LoginController::class,'showAdminLoginForm'])->name('admin.login-view');
Route::post('/admin',[LoginController::class,'adminLogin'])->name('admin.login');

Route::get('/admin/register',[RegisterController::class,'showAdminRegisterForm'])->name('admin.register-view');
Route::post('/admin/register',[RegisterController::class,'createAdmin'])->name('admin.register');

Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
Route::get('/admin/dashboard',function(){
    return view('admin');
})->middleware('auth:admin');

Step 13: Modify RedirectIfAuthenticated.php Middleware

It is important you modify how users are redirected when they are authenticated. Laravel by default redirects all authenticated users to /home. We will get the error below if we do not modify the redirection.

open the app/Http/Controllers/Middleware/RedirectIfAuthenticated.php file and replace with this:

<?php

namespace App\Http\Middleware;

use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

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

        foreach ($guards as $guard) {

            if ($guard == "admin" && Auth::guard($guard)->check()) {
                return redirect('/admin/dashboard');
            }

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

        return $next($request);
    }
}

The RedirectIfAuthenticated middleware receives the auth guard as a parameter. This middleware is triggered when we try to visit any page meant for authenticated users.

Step 14: Modify authentication exception handler

Open the handler file  app/Exceptions/Handler.php and add the following:

<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Auth\AuthenticationException;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of exception types with their corresponding custom log levels.
     *
     * @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
     */
    protected $levels = [
        //
    ];

    /**
     * A list of the exception types that are not reported.
     *
     * @var array<int, class-string<\Throwable>>
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed to the session on validation exceptions.
     *
     * @var array<int, string>
     */
    protected $dontFlash = [
        'current_password',
        'password',
        'password_confirmation',
    ];

    /**
     * Register the exception handling callbacks for the application.
     *
     * @return void
     */
    public function register()
    {
        $this->reportable(function (Throwable $e) {
            //
        });
    }

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['message' => 'Unauthenticated.'], 401);
        }

        if ($request->is('admin') || $request->is('admin/*')) {
            return redirect()->guest('/admin');
        }
        
        return redirect()->guest(route('login'));
    }
}

The unauthenticated the method we just added resolves this issue we have. It receives an AuthenticationExpection exception by default which carries that guard information.

Our workaround is to use request->is(). This checks the URL we are trying to access. It can also check the URL pattern if we do not have an absolute URL or if we have a route group.

In our case, we first check if we received a JSON request and handle the exception separately. Then we check if we are trying to access /admin any URL preceded by admin. We redirect the user to the appropriate login page.

This is a good workaround for us, but it means we must know the absolute URL we want to access, or at least have the same prefix for all routes that will be protected by our guard.

Step 15: Run the application

Now that our application is ready, run the following command to get it up:

php artisan serve

Most Probably Application URL will be http://localhost:8000.

Remember to visit http://localhost:8000/admin and http://localhost:8000/admin/register.

Conclusion

In this article, we dived deep into Laravel authentication. We defined multiple guards to handle multiple authentications and access control. We also handle redirection for authenticated users and redirection for unauthenticated users.

The source code to the application in this article is available on Github.

Thank you for reading this blog.

Read Also: How to Create Custom Validation Rules in Laravel 9

If you want to manage your VPS / VM Server without touching the command line go and  Checkout this linkServerAvatar allows you to quickly set up WordPress or Custom PHP websites on VPS / VM in a  matter of minutes.  You can host multiple websites on a single VPS / VM, configure SSL certificates, and monitor the health of your server without ever touching the command line interface.

If you have any queries or doubts about this topic please feel free to contact us. We will try to reach you.

Comments (18)

Hoàng Hoàng 7 months ago

Call to a member function count() on null

partha partha 10 months ago

if (\Auth::guard('admin')->attempt($request->only(['email','password']), $request->get('remember'))){ return redirect()->intended('/admin/dashboard'); }

Undefined type 'Auth'.

partha partha 10 months ago

on click logout

Target class [App\Http\Controllers\Auth\LoginController] does not exist.

| 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 = RouteServiceProvider::HOME; /* * Create a new controller instance. * * @return void / public function __construct() { $this->middleware('guest')->except('logout'); $this->middleware('guest:admin')->except('logout'); } public function showAdminLoginForm() { return view('auth.login', ['url' => route('admin.login-view'), 'title'=>'Admin']); } public function adminLogin(Request $request) { $this->validate($request, [ 'email' => 'required|email', 'password' => 'required|min:6' ]); if (\Auth::guard('admin')->attempt($request->only(['email','password']), $request->get('remember'))){ return redirect()->intended('/admin/dashboard'); } return back()->withInput($request->only('email', 'remember')); } }namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; class LoginController 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 = RouteServiceProvider::HOME; /* * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest')->except('logout'); $this->middleware('guest:admin')->except('logout'); } public function showAdminLoginForm() { return view('auth.login', ['url' => route('admin.login-view'), 'title'=>'Admin']); } public function adminLogin(Request $request) { $this->validate($request, [ 'email' => 'required|email', 'password' => 'required|min:6' ]); if (\Auth::guard('admin')->attempt($request->only(['email','password']), $request->get('remember'))){ return redirect()->intended('/admin/dashboard'); } return back()->withInput($request->only('email', 'remember')); } }

Ahmed Ahmed 10 months ago

you must update login form to route "admin.login"

prithiviraj khumukcham prithiviraj khumukcham 1 year ago

I have done as instructed, and the Welcome page is fine, but after routing to register or login it keeps giving error Target class [guest.admin] does not exist.

Nasuco Nasuco 1 year ago

How do I make it run on postman?

haseeb hassan haseeb hassan 1 year ago

if we logout admin it also logout user

jawad jawad 1 year ago

public function logout(){ Auth::guard('admin')->logout();

return redirect()->route('admin.login');}

Vajirali Vajirali 1 year ago

Thank you. I have follow one by one step and it working Perfectly.

Badhon Rahman Badhon Rahman 1 year ago

** Implemented it working fine. But there is a mistake in the code. In the login.blade.php the code will be as follows**

            <div class="card-header text-danger">{{ $title ?? "" }} {{ __('Login') }}</div>
            <div class="card-body bg-dark">
                @isset($url)
                    <form method="POST" action="{{ $url }}">
                @else
                    <form method="POST" action="{{ route('login') }}">
                @endisset
Sabin Sabin 1 year ago

I have done as you instructed, and I created an admin, but when I tried to login as admin with the same credentials, it showed that the credentials did not match our records.

Ikechukwu Akandu Ikechukwu Akandu 1 year ago

To resolve this add 'use Illuminate\Foundation\Auth\User as Authenticatable;' to your admin model and extends Authenticatable.

dew dew 1 year ago

I've done this and literally copied and pasted all the codes. Admin register works fine. But admin login still showed that the credentials doesn't match our records

Albert Albert 11 months ago

I also have the same problem, have you found a solution?

Mohamed Ahmed Mohamed Ahmed 8 months ago

It's working fine but this problem occurs because of a minor issue in the login blade in the form's action. User credentials do not exist because the action of the form directs to the user login function.The action of the form should direct to route('admin.login') not route('login.') .

                @else
                    <form method="POST" action="{{ route('admin.login') }}">
                @endisset
Rodolfo Rodolfo 1 year ago

In Laravel 9 we dont have the trait Illuminate\Foundation\Auth\AuthenticatesUsers;

Are your code really revised for laravel 9 ?

elhussini elhussini 1 year ago

How to show Auth Data after login like name

Suresh Ramani Suresh Ramani 1 year ago

You can use auth()->user()->name or \Auth::user()->name.

Comment


Note: All Input Fields are required.