Reputation: 16344
I am having troubles understanding how could I implement multiple connexions for same user via password client with Laravel Passport:
I have a mobile app, that needs to communicate with a Laravel based API. My users, at first launch of the app, will have to enter their login
and password
to get an access_token
.
So I think that I need to put my password client secret
in the code of my mobile app to be able to request tokens. But what if, my user has an iPhone and an iPad and he wants to login from both.
I'm asking because every time I make a request to POST /oauth/token
, from the same password_client
, every access_token
of a certain user
requested with my password_client
gets revoked
.
That would mean that, every time my user would use his iPad, he would be disconnected from his iPhone because the token wouldn't be valid anymore?
Am I missing something?
Upvotes: 2
Views: 6433
Reputation: 860
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();
}
Upvotes: 0
Reputation: 413
I believe that Passport changed the way it was dealing with the Access Token creation and the method @issueToken in AccessTokenController
does no longer revoke old tokens (check Multiple Access Token).
I think that this change was introduced before @jesús-lozano-m answer and therefore there is no longer the need to customize controller.
However, if you want to revoke old tokens, now you can do that by setting a listener to the Passport Event AccessTokenCreated
.
app/Providers/eventServiceProvider.php:
<?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('user_id', $event->userId)
->where('created_at', '<', Carbon::now()->subDay())
->delete();
}
}
Upvotes: 5
Reputation: 46
You can write your own Controller and Routes...
Passport has a defined "Laravel\Passport\Http\Controllers\AccessTokenController" and there is a method called "issueToken()".
If you see the method below it calls the function "revokeOtherAccessTokens()", and this deletes or revoke all "access_tokens" using the "Laravel\Passport\TokenRepository"
So what you can do is to write your own controller and prevent to call "revokeOtherAccessTokens()"
The fact that you must keep in mind is that the access tokens will never be pruned or revoked at least that the refresh token became issued or manually delete them.
Refresh tokens and access tokens are revoked when refresh token is issued, because the "League\OAuth2\Server\Grant\RefreshTokenGrant" in method "respondToAccessTokenRequest()", it already revoke old "access_token" and "refresh_token", so we don't have to worry about revoke or delete them in this case.
...
// Expire old tokens
$this->accessTokenRepository->revokeAccessToken($oldRefreshToken['access_token_id']);
$this->refreshTokenRepository->revokeRefreshToken($oldRefreshToken['refresh_token_id']);
...
Here is an sample implementation, hope it helps:
routes:
Route::post('oauth/access_token', 'Auth\OAuth2Controller@issueToken');
customized controller:
<?php
namespace App\Http\Controllers\Auth;
use Laravel\Passport\Http\Controllers\HandlesOAuthErrors;
use Zend\Diactoros\Response as Psr7Response;
use Psr\Http\Message\ServerRequestInterface;
use League\OAuth2\Server\AuthorizationServer;
use App\Http\Controllers\Controller;
class OAuth2Controller extends Controller
{
use HandlesOAuthErrors;
/**
* The authorization server.
*
* @var AuthorizationServer
*/
protected $server;
/**
* Create a new controller instance.
*
* @param AuthorizationServer $server
* @return void
*/
public function __construct(AuthorizationServer $server)
{
$this->server = $server;
}
/**
* Authorize a client to access the user's account.
*
* @param ServerRequestInterface $request
* @return Response
*/
public function issueToken(ServerRequestInterface $request)
{
return $this->withErrorHandling(function () use ($request) {
return $this->server->respondToAccessTokenRequest($request, new Psr7Response);
});
}
}
Upvotes: 3