Passport: Multiple Access Token

Created on 14 Sep 2016  ·  20Comments  ·  Source: laravel/passport

Is there an easy configuration to allow multiple access token per subject, so when user use different devices, old access tokens won't get revoke every time user request for a new access token on a different device

Most helpful comment

@shealan You need to properly include the AccessTokenCreated class in your listener.

All 20 comments

I am digging into this as well. Maybe there is a way if you override the the POST oauth/token route with your own controller class extending LaravelPassportHttpControllersAccessTokenController

There you could implement an issueToken function without the revokeOtherAccessTokens functionality.

Did not test anything of that.

I was thinking would you not register a separate client for each.
e.g. one for your web application, one for your android application, one for ios and one for wp ? which would allow you to be logged in to multiple devices at the same time ?

Yeah. I have registered different client for each. Sample Problem,. since your android app will use same client credentials, If a user have multiple android device or share one account with their trusted person, They can't use your app at the same time then, since one will get revoked, if you have set up your app to request a new access token once it got revoked using its refresh token, the other one would get revoked and had to do same thing. Both devices would keep hitting your server then.,

Maybe a new static field can be added for example Passport::$allowMultipleAccessTokens.

And prevent to call method revokeOtherAccessTokens() if it's true...

By now, this can be helpful...
http://stackoverflow.com/questions/39467566/laravel-passport-multiple-connexions-via-password-client/39802823#39802823

I have this implemented in my Lumen-Laravel passport integration package:
https://github.com/dusterio/lumen-passport

Upvoted. Being able to have multiple clients logged in per-client is pretty critical. And I can't think of any real benefit this provides from a security perspective. Instead it seems to be presuming how applications want to manage sessions, which shouldn't really be decided at this layer IMO.

You could perhaps add a maximum sessions per client setting, or implement a full authorized devices feature ala iTunes. But short of those, I think the default should be to allow infinite tokens.

Why this issue has been closed? Has this bug being resolved in any way? This is a critical issue for our users, with the current behaviour it's impossible to be logged in to two different browsers, for instance.

+1, why was this closed? Was it resolved? Duplicate? Pretty critical feature IMO.

Passport has been updated now with events triggering everytime a token is created, that way you can control when to revoke older tokens:

https://laravel.com/docs/5.3/passport#events

Thanks @themsaid . Does this mean that the default behavior has changed, and tokens will not be revoked automatically? If not, then how do we indicate revoke/not based on this event?

If it has changed, that's actually great for us but might be a breaking change for other developers worth highlighting.

@soundsgoodsofar The event setup has been put into the docs if you check here.

If you're curious about what to do with those events though, here is a quick example for the AccessTokenCreated event.

public function handle(AccessTokenCreated $event)
{
    DB::table('oauth_access_tokens')
        ->where('id', '<>', $event->tokenId)
        ->where('user_id', '=', $event->userId)
        ->where('client_id', '=', $event->clientId)
        ->update([
            'revoked' => true,
        ]);
}

Like @themsaid said, you have full control over it now, but that is a basic idea of what you might wanna implement.

@craigpaul the code makes sense, but unless the default behavior has changed, what you wrote would be superfluous.

The default behavior previously was to revoke all tokens for the same client. If that behavior has not changed, then a listener can't override the behavior--it's just a listener.

Is this actually just a listener, or is it a callback handler that overrides the default behavior somehow? Or did the default behavior change to not revoke other tokens? Unless one of those is true, I don't see how this could be used to solve the problem.

@soundsgoodsofar Sorry, forgot to address that part of your question. The default behaviour has changed. Tokens no longer get revoked from within Passport, instead those events get fired and allow the user to handle it how they wish. See #186 for more information, you'll see in the files changed, both revokeOtherAccessTokens methods no longer do anything. Hope that helps you out.

I understand that the change is breaking yeah, but the problems around this area were to many and we thought it might be better to give the user full control over it instead of forcing a convention.

@craigpaul @themsaid ah great! Makes sense now.

Yeah I think this is what the correct default behavior should be--just think it deserves a pretty prominent spot in the release notes since some people could be relying on the previous behavior for their security strategy.

Thanks guys!

@craigpaul I'm trying to use your example to clean up old tokens.

app/Providers/EventServiceProvider.php

    protected $listen = [
        'App\Events\SomeEvent' => [
            'App\Listeners\EventListener',
        ],
        'Laravel\Passport\Events\AccessTokenCreated' => [
            'App\Listeners\RevokeOldTokens',
        ]
    ];

app/Listeners/RevokeOldTokens.php

<?php

namespace App\Listeners;

class RevokeOldTokens
{
    public function handle(AccessTokenCreated $event)
    {
        DB::table('oauth_access_tokens')
            ->where('id', '<>', $event->tokenId)
            ->where('user_id', $event->userId)
            ->where('client_id', $event->clientId)
            ->update(['revoked' => true]);
    }
}

I'm getting the error:

Argument 1 passed to App\Listeners\RevokeOldTokens::handle() must be an instance of App\Listeners\AccessTokenCreated, instance of Laravel\Passport\Events\AccessTokenCreated given

I've looked and my version of Passport has the newly renamed AccessTokenCreated function.

Any ideas?

@shealan You need to properly include the AccessTokenCreated class in your listener.

Duh of course. Thank you @themsaid

@themsaid , in wich version of Laravel this commit go online?
I use Laravel Framework version 5.3.30, but I didn't found this modification.

Thank you!

I wirte below mention code in my app/Providers/AuthServiceProvider and its working. It won't removke old token and allow me login from multiple devicess

use Dusterio\LumenPassport\LumenPassport;

public function boot()
{
        $this->setPassportConfiguration();
}

private function setPassportConfiguration(): void
{
        LumenPassport::allowMultipleTokens();
}

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Adesubomi picture Adesubomi  ·  4Comments

gbgelado picture gbgelado  ·  3Comments

rudolfdobias picture rudolfdobias  ·  3Comments

parth-vora-7 picture parth-vora-7  ·  4Comments

mind-control picture mind-control  ·  3Comments