Search code examples
laravelapioauth-2.0laravel-passport

Issuing Access Tokens with Passport in limited lifetime


Backend : Laravel api. Frontend: Angular.

After setting up the Passport package on Laravel i use the regular way to authenticate user then issue token this way :

 $newToken = $user->createToken('myapp')->accessToken;

this works fine but the problem is the token life time is 1 year as it considered Personal Access Tokens and as documentation says :

Personal access tokens are always long-lived. Their lifetime is not modified when using the tokensExpireIn or refreshTokensExpireIn methods.

my question is how can i issue token for my user inside my application with limited lifetime ?

on the other hand it seems its dangerous to expose client_secred and client_id so i cant call oauth/token from my angular app


Solution

  • I'm sure it is not the best solution, but this is what i came up, many thanks to eightyfive answer:

    first add this protected method inside your authentication controller.

    protected function oauthLogin(Request $request)    
    {
        $client = DB::table('oauth_clients')
            ->where('password_client', true)
            ->first();    
        $request->request->add([
            "grant_type" => "password",
            "username" => $request->email,
            "password" => $request->password,
            "client_id" => $client->id,
            "client_secret" => $client->secret,
        ]);    
        $tokenRequest = $request->create(
            env('APP_URL') . '/oauth/token',
            'post'
        );    
        $instance = Route::dispatch($tokenRequest);    
        return json_decode($instance->getContent());    
    }
    

    then call the method inside login method only after authenticating the user:

    public function login(Request $request)
        {
    
            $credentials = $request->only('email', 'password');
            try {
                // verify the credentials and create a token for the user
                if ($token = Auth::guard('web')->attempt($credentials)) {
    
                    $user = Auth::guard('web')->user();
    
                    $roles = $user->roles()->get()->pluck('name');
    
                    $accessToken = $this->oauthLogin($request)->access_token; // instead of $user->createToken('token')->accessToken,
    
                    return response()->json([
                        'token' => $accessToken,
                        'roles' => $roles,
                        'email' => $request->input('email')
                    ]);
                } else {
                    return response()->json(['error' => 'invalid_credentials'], 401);
                }
            } catch (Exception $e) {
                // something went wrong
                return response()->json(['error' => 'could_not_create_token'], 500);
            }
        }
    

    this way the issued token is limited to the time you set in AuthServiceProvider.php :

    public function boot()
        {
            $this->registerPolicies();
    
            //
            Passport::routes();
    
            Passport::tokensExpireIn(now()->addHour(1));
    
            Passport::refreshTokensExpireIn(now()->addHour(1));
    
        }