Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cleanup for revoked tokens with appropriate indexes #234

Merged
merged 9 commits into from
Oct 24, 2020
133 changes: 133 additions & 0 deletions Command/ClearRevokedTokensCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Trikoder\Bundle\OAuth2Bundle\Manager\AccessTokenManagerInterface;
use Trikoder\Bundle\OAuth2Bundle\Manager\AuthorizationCodeManagerInterface;
use Trikoder\Bundle\OAuth2Bundle\Manager\RefreshTokenManagerInterface;

final class ClearRevokedTokensCommand extends Command
{
protected static $defaultName = 'trikoder:oauth2:clear-revoked-tokens';

/**
* @var AccessTokenManagerInterface
*/
private $accessTokenManager;

/**
* @var RefreshTokenManagerInterface
*/
private $refreshTokenManager;

/**
* @var AuthorizationCodeManagerInterface
*/
private $authorizationCodeManager;

public function __construct(
AccessTokenManagerInterface $accessTokenManager,
RefreshTokenManagerInterface $refreshTokenManager,
AuthorizationCodeManagerInterface $authorizationCodeManager
) {
parent::__construct();

$this->accessTokenManager = $accessTokenManager;
$this->refreshTokenManager = $refreshTokenManager;
$this->authorizationCodeManager = $authorizationCodeManager;
}

protected function configure(): void
{
$this
->setDescription('Clears all revoked access and/or refresh tokens and/or auth codes')
->addOption(
'access-tokens',
'a',
InputOption::VALUE_NONE,
'Clear revoked access tokens.'
)
->addOption(
'refresh-tokens',
'r',
InputOption::VALUE_NONE,
'Clear revoked refresh tokens.'
)
->addOption(
'auth-codes',
'c',
InputOption::VALUE_NONE,
'Clear revoked auth codes.'
)
;
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$clearRevokedAccessTokens = $input->getOption('access-tokens');
$clearRevokedRefreshTokens = $input->getOption('refresh-tokens');
$clearRevokedAuthCodes = $input->getOption('auth-codes');

if (!$clearRevokedAccessTokens && !$clearRevokedRefreshTokens && !$clearRevokedAuthCodes) {
$clearRevokedAccessTokens = true;
$clearRevokedRefreshTokens = true;
$clearRevokedAuthCodes = true;
}

if (true === $clearRevokedAccessTokens && $this->clearRevokedMethodExists($output, $this->accessTokenManager)) {
$affected = $this->accessTokenManager->clearRevoked();
X-Coder264 marked this conversation as resolved.
Show resolved Hide resolved
$output->writeln(
sprintf(
'Access tokens deleted: %s.',
$affected
)
);
}

if (true === $clearRevokedRefreshTokens && $this->clearRevokedMethodExists($output, $this->refreshTokenManager)) {
$affected = $this->refreshTokenManager->clearRevoked();
$output->writeln(
sprintf(
'Refresh tokens deleted: %s.',
$affected
)
);
}

if (true === $clearRevokedAuthCodes && $this->clearRevokedMethodExists($output, $this->authorizationCodeManager)) {
$affected = $this->authorizationCodeManager->clearRevoked();
$output->writeln(
sprintf(
'Auth codes deleted: %s.',
$affected
)
);
}

return 0;
}

private function clearRevokedMethodExists(OutputInterface $output, object $manager): bool
{
$methodName = 'clearRevoked';
$exists = method_exists($manager, $methodName);

if (!$exists) {
$output->writeln(
sprintf(
'<comment>Method "%s:%s()" will be required in the next major release. Skipping for now...</comment>',
\get_class($manager),
$methodName
)
);
}

return $exists;
}
}
3 changes: 3 additions & 0 deletions Manager/AccessTokenManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use Trikoder\Bundle\OAuth2Bundle\Model\AccessToken;

/**
* @method int clearRevoked() not defining this method is deprecated since version 3.2
*/
interface AccessTokenManagerInterface
{
public function find(string $identifier): ?AccessToken;
Expand Down
3 changes: 3 additions & 0 deletions Manager/AuthorizationCodeManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use Trikoder\Bundle\OAuth2Bundle\Model\AuthorizationCode;

/**
* @method int clearRevoked() not defining this method is deprecated since version 3.2
*/
interface AuthorizationCodeManagerInterface
{
public function find(string $identifier): ?AuthorizationCode;
Expand Down
9 changes: 9 additions & 0 deletions Manager/Doctrine/AccessTokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,13 @@ public function clearExpired(): int
->getQuery()
->execute();
}

public function clearRevoked(): int
{
return $this->entityManager->createQueryBuilder()
->delete(AccessToken::class, 'at')
->where('at.revoked = true')
->getQuery()
->execute();
}
}
9 changes: 9 additions & 0 deletions Manager/Doctrine/AuthorizationCodeManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,13 @@ public function clearExpired(): int
->getQuery()
->execute();
}

public function clearRevoked(): int
{
return $this->entityManager->createQueryBuilder()
->delete(AuthorizationCode::class, 'ac')
->where('ac.revoked = true')
->getQuery()
->execute();
}
}
9 changes: 9 additions & 0 deletions Manager/Doctrine/RefreshTokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,13 @@ public function clearExpired(): int
->getQuery()
->execute();
}

public function clearRevoked(): int
{
return $this->entityManager->createQueryBuilder()
->delete(RefreshToken::class, 'rt')
->where('rt.revoked = true')
->getQuery()
->execute();
}
}
11 changes: 11 additions & 0 deletions Manager/InMemory/AccessTokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,15 @@ public function clearExpired(): int

return $count - \count($this->accessTokens);
}

public function clearRevoked(): int
{
$count = \count($this->accessTokens);

$this->accessTokens = array_filter($this->accessTokens, static function (AccessToken $accessToken): bool {
return !$accessToken->isRevoked();
});

return $count - \count($this->accessTokens);
}
}
11 changes: 11 additions & 0 deletions Manager/InMemory/AuthorizationCodeManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,15 @@ public function clearExpired(): int

return $count - \count($this->authorizationCodes);
}

public function clearRevoked(): int
{
$count = \count($this->authorizationCodes);

$this->authorizationCodes = array_filter($this->authorizationCodes, static function (AuthorizationCode $authorizationCode): bool {
return !$authorizationCode->isRevoked();
});

return $count - \count($this->authorizationCodes);
}
}
11 changes: 11 additions & 0 deletions Manager/InMemory/RefreshTokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,15 @@ public function clearExpired(): int

return $count - \count($this->refreshTokens);
}

public function clearRevoked(): int
{
$count = \count($this->refreshTokens);

$this->refreshTokens = array_filter($this->refreshTokens, static function (RefreshToken $refreshToken): bool {
return !$refreshToken->isRevoked();
});

return $count - \count($this->refreshTokens);
}
}
3 changes: 3 additions & 0 deletions Manager/RefreshTokenManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use Trikoder\Bundle\OAuth2Bundle\Model\RefreshToken;

/**
* @method int clearRevoked() not defining this method is deprecated since version 3.2
*/
interface RefreshTokenManagerInterface
{
public function find(string $identifier): ?RefreshToken;
Expand Down
7 changes: 7 additions & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@
<deprecated>The "%alias_id%" service alias is deprecated and will be removed in v4.</deprecated>
</service>

<service id="Trikoder\Bundle\OAuth2Bundle\Command\ClearRevokedTokensCommand">
<argument type="service" id="Trikoder\Bundle\OAuth2Bundle\Manager\AccessTokenManagerInterface" />
<argument type="service" id="Trikoder\Bundle\OAuth2Bundle\Manager\RefreshTokenManagerInterface" />
<argument type="service" id="Trikoder\Bundle\OAuth2Bundle\Manager\AuthorizationCodeManagerInterface" />
<tag name="console.command" />
</service>

<!-- Utility services -->
<service id="Trikoder\Bundle\OAuth2Bundle\Converter\UserConverter" />
<service id="trikoder.oauth2.converter.user_converter" alias="Trikoder\Bundle\OAuth2Bundle\Converter\UserConverter">
Expand Down
Loading