Skip to content
Advertisement

OAuth: Proper way to generate/reuse token

This is how I manage the OAuth authentication when a user gives correct credentials:

    protected function authenticated(Request $request, User $user)
    {
        return response()->json([
            'token' => $user->createToken('my_app')->accessToken
        ]);
    }

I try to use the default Laravel authentication (passport), which uses OAuth. The problem I have is each time a user connects, it creates a new entry in the oauth_access_token table.

What is the recommended way to do it ?

Let it grow like that, having nb_user * nb_authentications entries in this table ?

Or should I check if the user already has a valid token when he authenticates to give it back to him, or deleting the other tokens when a new one is created ?

Advertisement

Answer

It is the responsibility of the user and the client to keep his access token code, and an appropriate mechanism must be made by the client application and store the key in a safe place.

Also, a secure connection must be used while generating the key like using https. Later on, generating access tokens for the user whenever the login page is requested will be considered a security vulnerability as the database will contain many access tokens that have validity and can be used and difficult to track.

Therefore, the preferred method of handling this is that we delete the previous access tokens that were created for the user as soon as the new key access token created.

The recommended way in Laravel 7 [See the official documentation] is to use events to track the generation and delete the old ones:

Inside the EventServiceProvider class, find the $listen array and append the Passport listener:

'LaravelPassportEventsAccessTokenCreated' => [
            'AppListenersRevokeOldTokens',
        ],

Then we execute the following artisan command to generate the listener:

php artisan event:generate

Then locate the listener inside the AppListeners folder and inside the handle method put the following code:

Token::where([
            ['user_id', $event->userId],
            ['id', '<>', $event->tokenId]
        ])->delete();

By writing the above code, we tell Laravel to find user access tokens via his userID, who has created a new access token, and that the access token ID is not the same as the new access token ID just generated. When this data is in the database, meaning that the user has old access tokens, we delete them.

The content of the listener class file is as follows:

<?php

namespace AppListeners;

use LaravelPassportEventsAccessTokenCreated;
use IlluminateContractsQueueShouldQueue;
use IlluminateQueueInteractsWithQueue;
use LaravelPassportToken;

class RevokeOldTokens
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  AccessTokenCreated  $event
     * @return void
     */
    public function handle(AccessTokenCreated $event)
    {
        Token::where([
            ['user_id', $event->userId],
            ['id', '<>', $event->tokenId]
        ])->delete();
    }
}

Now try generating a new user access code and you will notice that the previous access tokens are deleted from the database.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement