From 564f55c181e605de227c97fddec3425b9f980226 Mon Sep 17 00:00:00 2001 From: Alexander Karlstad Date: Wed, 13 Jan 2021 22:48:44 +0100 Subject: [PATCH 1/5] Delete invalid refresh tokens Delete refresh tokens referring to non-existing access tokens. --- src/Console/PurgeCommand.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index 7854c6ab2..3a638569c 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -36,18 +36,27 @@ public function handle() Passport::token()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); + Passport::refreshToken()->whereNotIn('access_token_id', function($subQuery) { + $subQuery->select('id')->from(Passport::token()->getTable()); + })->delete(); $this->info('Purged revoked items and items expired for more than seven days.'); } elseif ($this->option('revoked')) { Passport::token()->where('revoked', 1)->delete(); Passport::authCode()->where('revoked', 1)->delete(); Passport::refreshToken()->where('revoked', 1)->delete(); + Passport::refreshToken()->whereNotIn('access_token_id', function($subQuery) { + $subQuery->select('id')->from(Passport::token()->getTable()); + })->delete(); $this->info('Purged revoked items.'); } elseif ($this->option('expired')) { Passport::token()->whereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); + Passport::refreshToken()->whereNotIn('access_token_id', function($subQuery) { + $subQuery->select('id')->from(Passport::token()->getTable()); + })->delete(); $this->info('Purged items expired for more than seven days.'); } From 22402a217cb1f66dba5ce835b669e7f897f68280 Mon Sep 17 00:00:00 2001 From: Alexander Karlstad Date: Wed, 13 Jan 2021 23:03:31 +0100 Subject: [PATCH 2/5] Use whereDoesntHave() instead --- src/Console/PurgeCommand.php | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index 3a638569c..cf5b78ddb 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -36,27 +36,21 @@ public function handle() Passport::token()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); - Passport::refreshToken()->whereNotIn('access_token_id', function($subQuery) { - $subQuery->select('id')->from(Passport::token()->getTable()); - })->delete(); + Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); $this->info('Purged revoked items and items expired for more than seven days.'); } elseif ($this->option('revoked')) { Passport::token()->where('revoked', 1)->delete(); Passport::authCode()->where('revoked', 1)->delete(); Passport::refreshToken()->where('revoked', 1)->delete(); - Passport::refreshToken()->whereNotIn('access_token_id', function($subQuery) { - $subQuery->select('id')->from(Passport::token()->getTable()); - })->delete(); + Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); $this->info('Purged revoked items.'); } elseif ($this->option('expired')) { Passport::token()->whereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); - Passport::refreshToken()->whereNotIn('access_token_id', function($subQuery) { - $subQuery->select('id')->from(Passport::token()->getTable()); - })->delete(); + Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); $this->info('Purged items expired for more than seven days.'); } From d18fbdf7e5201c9847f8c9dc23542fcd969daf2e Mon Sep 17 00:00:00 2001 From: Alexander Karlstad Date: Thu, 14 Jan 2021 12:10:55 +0100 Subject: [PATCH 3/5] Add test for purge command --- tests/Feature/Console/PurgeCommand.php | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/Feature/Console/PurgeCommand.php diff --git a/tests/Feature/Console/PurgeCommand.php b/tests/Feature/Console/PurgeCommand.php new file mode 100644 index 000000000..baed3424d --- /dev/null +++ b/tests/Feature/Console/PurgeCommand.php @@ -0,0 +1,45 @@ +subDays(8); + $notExpired = now(); + + $accessTokenExpired = Token::create(['id' => 'a', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $expired]); + $accessTokenRevoked = Token::create(['id' => 'b', 'user_id' => 1, 'client_id' => 1, 'revoked' => 1, 'expires_at' => $notExpired]); + $accessTokenOk = Token::create(['id' => 'c', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $notExpired]); + + $authCodeExpired = AuthCode::create(['id' => 'a', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $expired]); + $authCodeRevoked = AuthCode::create(['id' => 'b', 'user_id' => 1, 'client_id' => 1, 'revoked' => 1, 'expires_at' => $notExpired]); + $authCodeOk = AuthCode::create(['id' => 'c', 'user_id' => 1, 'client_id' => 1, 'revoked' => 0, 'expires_at' => $notExpired]); + + $refreshTokenExpired = RefreshToken::create(['id' => 'a', 'access_token_id' => $accessTokenExpired->id, 'revoked' => 0, 'expires_at' => $expired]); + $refreshTokenRevoked = RefreshToken::create(['id' => 'b', 'access_token_id' => $accessTokenRevoked->id, 'revoked' => 1, 'expires_at' => $notExpired]); + $refreshTokenInvalidAccessToken = RefreshToken::create(['id' => 'c', 'access_token_id' => 'xyz', 'revoked' => 0, 'expires_at' => $notExpired]); + $refreshTokenOk = RefreshToken::create(['id' => 'd', 'access_token_id' => $accessTokenOk->id, 'revoked' => 0, 'expires_at' => $notExpired]); + + $this->artisan('passport:purge'); + + $this->assertFalse(Token::whereKey($accessTokenExpired->id)->exists()); + $this->assertFalse(Token::whereKey($accessTokenRevoked->id)->exists()); + $this->assertTrue(Token::whereKey($accessTokenOk->id)->exists()); + + $this->assertFalse(AuthCode::whereKey($authCodeExpired->id)->exists()); + $this->assertFalse(AuthCode::whereKey($authCodeRevoked->id)->exists()); + $this->assertTrue(AuthCode::whereKey($authCodeOk->id)->exists()); + + $this->assertFalse(RefreshToken::whereKey($refreshTokenExpired->id)->exists()); + $this->assertFalse(RefreshToken::whereKey($refreshTokenRevoked->id)->exists()); + $this->assertFalse(RefreshToken::whereKey($refreshTokenInvalidAccessToken->id)->exists()); + $this->assertTrue(RefreshToken::whereKey($refreshTokenOk->id)->exists()); + } +} From e75e9e35e445ebf45f5cdf7845d9494e36449558 Mon Sep 17 00:00:00 2001 From: Alexander Karlstad Date: Thu, 14 Jan 2021 12:13:21 +0100 Subject: [PATCH 4/5] Update description and output of command --- src/Console/PurgeCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index cf5b78ddb..c6fa87971 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -22,7 +22,7 @@ class PurgeCommand extends Command * * @var string */ - protected $description = 'Purge revoked and / or expired tokens and authentication codes'; + protected $description = 'Purge revoked and / or expired tokens and authentication codes, and invalid refresh tokens.'; /** * Execute the console command. @@ -38,21 +38,21 @@ public function handle() Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged revoked items and items expired for more than seven days.'); + $this->info('Purged invalid refresh tokens, revoked items and items expired for more than seven days.'); } elseif ($this->option('revoked')) { Passport::token()->where('revoked', 1)->delete(); Passport::authCode()->where('revoked', 1)->delete(); Passport::refreshToken()->where('revoked', 1)->delete(); Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged revoked items.'); + $this->info('Purged invalid refresh tokens and revoked items.'); } elseif ($this->option('expired')) { Passport::token()->whereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged items expired for more than seven days.'); + $this->info('Purged invalid refresh tokens and items expired for more than seven days.'); } } } From 94ba84bf61b684ab8f62c4f9d967f1f2c4ab7688 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 14 Jan 2021 08:11:39 -0600 Subject: [PATCH 5/5] Update PurgeCommand.php --- src/Console/PurgeCommand.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index c6fa87971..7b97783f1 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -22,7 +22,7 @@ class PurgeCommand extends Command * * @var string */ - protected $description = 'Purge revoked and / or expired tokens and authentication codes, and invalid refresh tokens.'; + protected $description = 'Purge revoked and / or expired tokens, authentication codes, and refresh tokens.'; /** * Execute the console command. @@ -38,21 +38,21 @@ public function handle() Passport::refreshToken()->where('revoked', 1)->orWhereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged invalid refresh tokens, revoked items and items expired for more than seven days.'); + $this->info('Purged invalid refresh tokens, revoked tokens, and tokens expired for more than seven days.'); } elseif ($this->option('revoked')) { Passport::token()->where('revoked', 1)->delete(); Passport::authCode()->where('revoked', 1)->delete(); Passport::refreshToken()->where('revoked', 1)->delete(); Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged invalid refresh tokens and revoked items.'); + $this->info('Purged invalid refresh tokens and revoked tokens.'); } elseif ($this->option('expired')) { Passport::token()->whereDate('expires_at', '<', $expired)->delete(); Passport::authCode()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDate('expires_at', '<', $expired)->delete(); Passport::refreshToken()->whereDoesntHave('accessToken')->delete(); - $this->info('Purged invalid refresh tokens and items expired for more than seven days.'); + $this->info('Purged invalid refresh tokens and tokens expired for more than seven days.'); } } }