Multiple User Models Laravel JWT Auth

ぃ、小莉子 提交于 2021-02-07 03:12:51

问题


I have to user models in my eloquent:

  • User
  • OfficeUser

OfficeUser is in defined in the JWT config as standard model. Now I have written a Middleware for authenticate each of them

authUser:

public function handle($request, Closure $next)
{
    Config::set('auth.providers.users.model', \App\User::class);
    try {

        if (! $user = JWTAuth::parseToken()->authenticate()) {
            return response()->json(['user_not_found'], 404);
        }

    } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {

        return response()->json(['token_expired'], $e->getStatusCode());

    } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {

        return response()->json(['token_invalid'], $e->getStatusCode());

    } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {

        return response()->json(['token_absent'], $e->getStatusCode());

    }

    return $next($request);
}

authOfficeUser

public function handle($request, Closure $next)
{
    try {

        if (! $user = JWTAuth::parseToken()->authenticate()) {
            return response()->json(['user_not_found'], 404);
        }

    } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {

        return response()->json(['token_expired'], $e->getStatusCode());

    } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {

        return response()->json(['token_invalid'], $e->getStatusCode());

    } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {

        return response()->json(['token_absent'], $e->getStatusCode());

    }

    return $next($request);
}

Additionally I have a login function for each of them:

LoginUser

if ($user){
        if (Hash::check($request->password, $user->password)) {
            // grab credentials from the request
            $credentials = $request->only('email', 'password');

            try {
                // attempt to verify the credentials and create a token for the user
                Config::set('auth.providers.users.model', \App\User::class);
                if (! $token = JWTAuth::attempt($credentials)) {
                    return response()->json(['error' => 'invalid_credentials'], 401);
                }
            } catch (JWTException $e) {
                // something went wrong whilst attempting to encode the token
                return response()->json(['error' => 'could_not_create_token'], 500);
            }

LoginOfficeUser

if ($user){
        if (Hash::check($request->password, $user->password)) {
            // grab credentials from the request
            $credentials = $request->only('email', 'password');

            try {
                // attempt to verify the credentials and create a token for the user
                Config::set('auth.providers.users.model', \App\OfficeUser::class);
                if (! $token = JWTAuth::attempt($credentials)) {
                    return response()->json(['error' => 'invalid_credentials'], 401);
                }
            } catch (JWTException $e) {
                // something went wrong whilst attempting to encode the token
                return response()->json(['error' => 'could_not_create_token'], 500);
            }

Unfortunately when I login and try to call a route behind the authUser Middleware I get an "user_not_found"

Does anybody have an idea why this happens? OfficeUser authentication works fine


回答1:


Posting for anyone who finds this questions

Although it's not recommended to have two user tables, but I had a similar requirement of setting up JWT with one of our clients. This is how I solved the issue.

No need to make any changes to the providers in `config/auth.php'

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

]

In your authentication controller, dynamically modify the model used by the providers by setting

\Config::set('auth.providers.users.model', \App\Trainer::class);

Example code

In authenticate() method

if ($credentials['user_type'] == 'consultant') {

\Config::set('auth.providers.users.model', \App\Trainer::class);

} else {
    \Config::set('auth.providers.users.model', \App\User::class);
}

//Find the user

//Create the token
if ($user) {
   $customClaims = ['user_type' => $credentials['user_type']];
   $token = JWTAuth::fromUser($user,$customClaims);
} else {
  return response()->json(['error' => 'invalid_credentials'], 401);
}

You will have to do the same while parsing the token to authenticate the user as well. Example code

In getAuthenticatedUser() method

$payload = JWTAuth::parseToken()->getPayload();
$user_type = $payload->get('user_type');

if($user_type === 'consultant'){
   \Config::set('auth.providers.users.model', \App\Trainer::class);
}else{
   \Config::set('auth.providers.users.model', \App\User::class);
}

if (!$user = JWTAuth::parseToken()->authenticate()) {
    return response()->json(['user_not_found'], 404);
}



回答2:


You can change the __construct function in each of your controllers as follows. So that jwt know which model to authenticate.

OfficeUserController

function __construct()
{
    Config::set('jwt.user', OfficeUser::class);
    Config::set('auth.providers', ['users' => [
            'driver' => 'eloquent',
            'model' => OfficeUser::class,
        ]]);
}


来源:https://stackoverflow.com/questions/36839158/multiple-user-models-laravel-jwt-auth

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!