7

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

2 Answers 2

5

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);
}
Sign up to request clarification or add additional context in comments.

2 Comments

Ps: You should override the configuration changes in the controller constructor.
I have done all thing the same like you suggest still JWTAuth::parseToken()->authenticate() refers to the User model instead of the given model @amal Ajith
0

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,
        ]]);
}

Comments

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.