MirasMustimuly's avatar

Default authentication from multple tables

Hi, I need to authenticate users from two tables. So on any request I need my app to try to find user in the first table and if it doesnt find the user then search in the second table. My app doesnt have separate pages for these users, everything is common. Is there a way to do it?

0 likes
9 replies
jlrdw's avatar
jlrdw
Best Answer
Level 75

see https://laracasts.com/discuss/channels/laravel/role-based-access-control-using-fortify-or-multiple-authentication-system-using-fortify

Use authentication for login and then use authorization to determine what the logged in user can or cannot do.

Otherwise you may want to completely do your own RBAC system, which I advise against unless you have years of programming experience.

Another link:

https://laracasts.com/discuss/channels/laravel/laravel-8-multi-auth-using-jetstream-fortify

2 likes
MirasMustimuly's avatar

Hi, thank you for your answer. But my problem is that I am able to log a user in, but on the consequent request laravel is unable to fetch the user from the right table. Authorization and logging a user in is not a problem/

MirasMustimuly's avatar

This is how I managed to impolement it

Logging a user in

// this is where I try to fetch user by two tables
if (! $user = $this->getUserByEmail($request->email)) {
    return back()->withFlash('Email is not found.');
}

if (!Password::check($user, $request->password)) {
    return back()->withFlash('Wrong pass.');
}

if ($user instanceOf RetailUser) {
    auth()->shouldUse($retailUsersGuard = 'web_retail'); // change current guard
    session()->put('auth_guard', $retailUsersGuard); // persist guard into session, to use it in consequent requests 
}

auth()->login($user);

and middleware to change guard on each request

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Session;

class SetGuard
{
    public function handle($request, Closure $next, $guard = null)
    {
        if (session()->has('auth_guard')) {
            app('auth')->shouldUse(session('auth_guard'));
        }

        return $next($request);
    }
}


martinbean's avatar

@mirasmustimov Why? A user is a user. Have one user table and then use roles to authorise what they can see and what they can do.

1 like
MirasMustimuly's avatar

Thank you for your answer. Unfortunately this is an arhcitectural restriction of another system we depend on

jlrdw's avatar

@mirasmustimov that's because out of the box Authentication it's not geared up for two tables.

In one of the links above, there are other links that explain how to do multi Authentication.

Laravel Authentication is looking for the users table, not some custom table. But go over the links I gave.

1 like
slev1n's avatar

@mirasmustimov you need to make your own guard with custom UserProvider.

check this articles

https://laravel.com/docs/8.x/authentication#adding-custom-guards

https://laravel.com/docs/8.x/authentication#adding-custom-user-providers

https://laravel.com/docs/8.x/authentication#the-user-provider-contract

<?php

namespace Illuminate\Contracts\Auth;

interface UserProvider
{
    public function retrieveById($identifier);
    public function retrieveByToken($identifier, $token);
    public function updateRememberToken(Authenticatable $user, $token);
    public function retrieveByCredentials(array $credentials);
    public function validateCredentials(Authenticatable $user, array $credentials);
}
1 like
slev1n's avatar

in this case you need change default user identifier name. On default id next request auth logic will fails, i suppose.

You can do it or via Table.php -> protected $primaryKey (bad way) or via reloading Authenticatable trait's getAuthIdentifierName() method.

Also all tables must use Authenticatable trait.

Please or to participate in this conversation.