Search code examples
laravellaravel-passport

Is it possible to avoid huge number of access tokens in database?


I've built a RESTful API with a Laravel Passport project.
It's using the Client Credentials Grant to authorize my third party project.
The problem is that for each api call from the third party application it generates a new access token.
By the end of the day, if i had 999 calls i will have also 999 new records in the oauth_access_tokens database table.
It's possible to avoid huge number of access tokens in database?

Maybe in League\OAuth2\Server\Grant\ClientCredentialsGrant.php:

public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, \DateInterval $accessTokenTTL) {
    $client = $this->validateClient($request);
    $scopes = $this->validateScopes($this->getRequestParameter('scope', $request));
    $scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client);
    // $validToken = query to check if $client has existing token neither revoked or expired
    // if ($validToken) { 
    //     return $responseType->setAccessToken($validToken);
    // }
    $accessToken = $this->issueAccessToken($accessTokenTTL, $client, null, $scopes);
    $responseType->setAccessToken($accessToken);
    return $responseType;
}

Solution

  • Solution
    Set a listener to the event generated by Passport when a access token is created.

    app/Providers/eventServiceProvider.php:

    namespace App\Providers;
    
    use Illuminate\Support\Facades\Event;
    use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
    
    class EventServiceProvider extends ServiceProvider {
        protected $listen = [
            'Laravel\Passport\Events\AccessTokenCreated' => [
                'App\Listeners\RevokeOldTokens'
            ]
        ];
        public function boot() {
            parent::boot();
        }
    }
    

    app/Listeners/RevokeOldTokens.php:

    <?php
    
    namespace App\Listeners;
    
    use Laravel\Passport\Events\AccessTokenCreated;
    use Laravel\Passport\Client;
    use Carbon\Carbon;
    
    class RevokeOldTokens {
        public function __construct() {
            //
        }
        public function handle(AccessTokenCreated $event) {
            $client = Client::find($event->clientId);
            // delete this client tokens created before one day ago:
            $client->tokens()->where('created_at', '<', Carbon::now()->subDay())->forceDelete();
        }
    }