tymondesigns / jwt-auth

🔐 JSON Web Token Authentication for Laravel & Lumen
https://jwt-auth.com
MIT License
11.31k stars 1.55k forks source link

Multi Jwt Auth with Laravel and Mongodb #1599

Open behnamazimi opened 6 years ago

behnamazimi commented 6 years ago

As I explained in my StackOverflow question, I have three authenticatable models and I want JWT to work with each separately.

Even when I change the jwt.user and auth.providers.users.model values manually in config files, it does not effect on my JWT auth.

After some deep search in codes, I could not find any method to change default user model before byCredentials method of AuthInterface that call in JWTAuth::attempt method.

I really don't know what should I do to solve this!

behnamazimi commented 6 years ago

Multi Jwt Auth with Laravel and MongoDB

At first, when I faced this problem I asked a question on Stack Overflow, I suggest reading that before continue.

Solution:

After many kinds of research, Here is what I did to add multi auth ability with JWT to my project.

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

  2. I 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. I defined a function with name modifyJWTAuthUser in my 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. I 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 I want.

But even with this steps, I 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:

I created a new middleware CustomGetUserFrom Token which extends of Tymon's jwt.auth middleware, I mean GetUserFromToken and in line 35, I replaced $user = $this->auth->authenticate($token); with $user = JWTAuth::toUser($token);

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

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

$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.

dmitrymalys commented 5 years ago

Have you tried this approach link? It seems much more cleaner.

stale[bot] commented 3 years ago

Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.