3

I have a Laravel 12 with 2 guards "web" and "admin", the admin guard has its own user table "admins" (privacy concerns).

We have 2 Models "User" and "Admin", the Admin Model starts like:

{
    use HasFactory, HasRoles, Notifiable, SoftDeletes, TwoFactorAuthenticatable;

    protected string $guard_name = 'admin';
    protected $table = 'admins';

--snip--

both are configured in config/auth.php like:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'admin' => [
        'driver' => 'session',
        'provider' => 'admin',
    ],
],
'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'admin' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
    ],
'passwords' => [
    'users' => [
        'provider' => 'users',
        'table' => 'password_reset_tokens',
        'expire' => 60,
        'throttle' => 60,
    ],
    'admin' => [
        'provider' => 'admin',
        'table' => 'password_reset_tokens_admin',
        'expire' => 60,
        'throttle' => 60,
    ],
],

Everything is working for the web guard. I can register, login and see my profile with both usergroups/guards.

What does NOT work for admin guard is Fortify's 2FA "confirm password" route.

When i click on "2FA Authentication" as "admin", i get redirected to the "Confirm Password" route of the wrong guard "web", I am not logged in with "web", so I get redirected to "web" Login.

It works for the admin guard, when i change register() in FortifyServiceProvider.php like this:

config(['fortify.guard' => 'admin']);
config(['fortify.passwords' => 'admins']);
config(['fortify.home' => '/admin/dashboard']);

I tried to change the config values based on the session, but there is no session yet on ServiceProvider level, the session will only get initialized later in the framework.

Someone has a solution for that?

1 Answer 1

1

Fortify always uses the guard defined in config('fortify.guard'). If you have multiple guards (web/admin), you must override Fortify’s confirm-password logic to choose the correct guard dynamically.

Laravel Fortify does not automatically detect the active guard, so features like Confirm Password and 2FA always fallback to:


fortify.guard

Since that value is static, your admin user gets redirected to the web version of the confirm-password route.

Trying to change it inside the ServiceProvider using config(['fortify.guard' => 'admin']) doesn’t work because the session and authentication system are not initialized yet.

Solution: Override Fortify's confirmPassword logic

In your FortifyServiceProvider::boot():

use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Fortify;

public function boot()
{
    // Select the correct confirm-password view
    Fortify::confirmPasswordView(function () {
        return request()->is('admin/*')
            ? view('admin.auth.confirm-password')
            : view('auth.confirm-password');
    });

    // Validate password using the correct guard
    Fortify::confirmPassword(function ($user, $password) {
        $guard = request()->is('admin/*') ? 'admin' : 'web';

        return Auth::guard($guard)->validate([
            'email' => $user->email,
            'password' => $password,
        ]);
    });
}

This fixes the issue:

  • Admin confirm-password uses the admin guard

  • Web confirm-password uses the web guard

  • No need to modify config values at runtime

  • Admin 2FA now works correctly

    Summary

    • Fortify doesn’t support multi-guard auto-detection

    • The fix is to override the confirmPassword handler and pick the guard based on the route

    • After this change, 2FA and password confirmation work for both user types

New contributor
Ariyo Ayomide is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your input, I am aware that I can use different routes for admin things. My Question was about using the same routes for 2FA, since register/login works out of the box with the same route for both guards. And btw: I know how to use AI, too. Thank you for using your tokens.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.