Multi Jwt Auth with Laravel and Mongodb Multi Jwt Auth with Laravel and Mongodb mongodb mongodb

Multi Jwt Auth with Laravel and Mongodb


Here is what you must fo to add multi auth ability with JWT to my project.

  1. In tymon JWT auth package. In JWTAuthServiceProvider, Change Tymon\JWTAuth\JWTAuth and Tymon\JWTAuth\Providers\User\UserInterface definition type from singleton to bind in bootBindings method.

  2. Defined a new middleware and below code is its handle method:

    public function handle($request, Closure $next){        if (!$request->header('Auth-Type')) {            return response()->json([                'success' => 0,                'result' => 'auth type could not found!'            ]);        }    switch ($request->header('Auth-Type')) {    case 'user':        $auth_class = 'App\User';        break;    case 'admin':        $auth_class = 'App\Admin';        break;    case 'provider':        $auth_class = 'App\ServiceProvider';        break;    default:        $auth_class = 'App\User';}if (!Helpers::modifyJWTAuthUser($auth_class))    return response()->json([        'status' => 0,        'error' => 'provider not found!'    ]);return $next($request);    }
  3. Defined a function with name modifyJWTAuthUser in Helpers and here is its inner:

    public static function modifyJWTAuthUser($user_class){if (!$user_class ||    (        $user_class != 'App\User' &&        $user_class != 'App\Admin' &&        $user_class != 'App\ServiceProvider'    ))    return false;try {    Config::set('jwt.user', $user_class);    Config::set('auth.providers.users.model', $user_class);    app()->make('tymon.jwt.provider.user');    return true;} catch (\Exception $e) {    return false;}    }
  4. Introduced another $routeMiddleware like below in Kernel.php:

    ...'modify.jwt.auth.user' => ChangeJWTAuthUser::class,

  5. and the last step, Adding 'modify.jwt.auth.user' middleware to the routes that you want.

But even with this steps, You must have encountered a new issue. It was about getting the auth token by credentials in login and getting auth user from the token. (It seems that changing config value not effect on JWTAuth::attempt($credentials) and $this->auth->authenticate($token))

To solve the getting auth user from the token issue:

Create a new middleware CustomGetUserFromTokenwhich extends of Tymon'sjwt.authmiddleware, I meanGetUserFromTokenand in line 35, and **replace**$user = $this->auth->authenticate($token);with$user = JWTAuth::toUser($token);`

And to solve getting the auth token by credentials in login issue:

At first, Find the auth user and after that, check the user existence and valid the password with Hash::check() method, if these conditions return true, Generate a token from the user. Here is login code:

$admin = Admin::where('email', $request->email)->first();if (!$admin || !Hash::check($request->get('password'), $admin->password)) {    return response()->json([        'success' => '0',        'error' => 'invalid_credentials'    ], 401);}

I'm not sure about this way but I think it's true until finding a correct way to do!

Conclusion:

Having multi JWT auth ability in Laravel perhaps have many other ways to do but I did like this and shared it to be helpful.

I think the only important point of this issue was app()->make('tymon.jwt.provider.user');, the ability to remake user provider after config values change.

Any other solutions will be appreciated.


You should use just one model (actually table) for authentication. When you save user and admin you can handle it. But when a user has request with jwt token, you cann't know which model will return (Admin or User)?

Use only User model for authentication and Admin model extends from User.

Redesign database like this:

users table : id, email, password, is_admin

user_details table : id, user_id, first_name, last_name, city_abbr, phone

admin_details table: id, user_id, name, phone

Put this your Admin Model for overriding all queries:

protected $table = "users";public function newQuery(){    return parent::newQuery()        ->where("is_admin", true);}