Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple User Models Laravel JWT Auth

Tags:

php

laravel

jwt

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

like image 774
Yann1ck Avatar asked Apr 25 '16 11:04

Yann1ck


1 Answers

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);
}
like image 171
Amal Ajith Avatar answered Nov 10 '22 20:11

Amal Ajith