Laravel 8 Multi Auth Guard using Fortify but unable to implement Forgot Password and Verify Email for Admin

2.2k views Asked by At

I implemented Fortify Multi Auth Guard (Admin and User) with Custom view. I have separate login view for admin and user. I have also implemented Forgot Password for user and it is working very well. I am just unable to implement Forgot Password for Admin. Further I also want to implement email verification for both Admin and User. I have found half solution Please allow me to explain:-

vendor/laravel/framework/src/illuminate/Auth/Passwords/PasswordBrokerManager.php

public function broker($name = null)
{
    $name = $name ?: $this->getDefaultDriver();
    return $this->brokers[$name] ?? ($this->brokers[$name] = $this->resolve($name));
}

If i modify the above method as below it works for user only

public function broker($name = null)
{
    $name = $name ?: $this->getDefaultDriver();
    return $this->brokers[$name[0]] ?? ($this->brokers[$name[0]] = $this->resolve($name[0]));
}

And If i modify the method as below it works for admin only

public function broker($name = null)
{
    $name = $name ?: $this->getDefaultDriver();
    return $this->brokers[$name[1]] ?? ($this->brokers[$name[1]] = $this->resolve($name[1]));
}

How will it work for both as per requirement ? What is the best way to override mentioned broker() method ?

config/auth.php

<?php

return [


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


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

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

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


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

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],


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


    'password_timeout' => 10800,

];

config/fortify.php

<?php

use App\Providers\RouteServiceProvider;
use Laravel\Fortify\Features;

return [

    'guard' => 'web',

    'passwords' => ['users', 'admins'],

    'username' => 'email',

    'email' => 'email',

    'home' => RouteServiceProvider::HOME,

    'prefix' => '',

    'domain' => null,

    'middleware' => ['web'],

    'limiters' => [
        'login' => 'login',
        'two-factor' => 'two-factor',
    ],

    'views' => true,

    'features' => [
        Features::registration(),
        Features::resetPasswords(),
        // Features::emailVerification(),
        Features::updateProfileInformation(),
        Features::updatePasswords(),
        Features::twoFactorAuthentication([
            'confirmPassword' => true,
        ]),
    ],

];
1

There are 1 answers

2
Prospero On

I implement this but for Tenancy, but the idea is the same once I handle for this 2 diff guards. In the auth.php similar but add to the 'defaults'

'defaults' => [
        'guard' => 'web',
        'passwords' => ['users','tenant'],  // in your case must be ['users','admins']
    ],

the rest is the same config for both, auth and fortify files. In my case I can identify by Tenancy package when handle tenant or main app user, then I do

public function broker($name = null)
{
   $name = $name ?: $this->getDefaultDriver();
   if (Tenancy::getTenant()) {
      return $this->brokers[$name[1]] ?? ($this->brokers[$name[1]] = $this->resolve($name[1]));
   }
   else
      return $this->brokers[$name[0]] ?? ($this->brokers[$name[0]] = $this->resolve($name[0]));
}

In your case, you have to find the way to pass to broker some flag that let you manage this, or do some more research if it's possible to manage it in the broker method of PasswordResetLinkController. Here you have the store method that you can check if the user's request is admin or not and give the brocker you need for each case

public function store(Request $request): Responsable
{
   $request->validate([Fortify::email() => 'required|email']);
       //see if here you can get the user through email credentials

   // We will send the password reset link to this user. Once we have attempted
   // to send the link, we will examine the response then see the message we
   // need to show to the user. Finally, we'll send out a proper response.
   $status = $this->broker()->sendResetLink($request->only(Fortify::email()));
  //......