Skip to content

Commit

Permalink
feature #32 add disable access token saving feature (Orkin)
Browse files Browse the repository at this point in the history
This PR was squashed before being merged into the 0.1-dev branch.

Discussion
----------

add disable access token saving feature

`@mtarld`  `@chalasr` this is the port of disabled access token saving feature 😉

Commits
-------

03e815d add disable access token saving feature
  • Loading branch information
chalasr committed Dec 19, 2021
2 parents 429864a + 03e815d commit f9f55a9
Show file tree
Hide file tree
Showing 14 changed files with 280 additions and 32 deletions.
3 changes: 3 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ For implementation into Symfony projects, please see [bundle documentation](docs
# Whether to require code challenge for public clients for the auth code grant
require_code_challenge_for_public_clients: true
# Whether to enable access token saving to persistence layer (default to true)
persist_access_token: true
resource_server: # Required
# Full path to the public key file
Expand Down
4 changes: 4 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ private function createAuthorizationServerNode(): NodeDefinition
->info('Whether to enable the implicit grant')
->defaultTrue()
->end()
->booleanNode('persist_access_token')
->info('Whether to enable access token saving to persistence layer')
->defaultTrue()
->end()
->end()
;

Expand Down
21 changes: 19 additions & 2 deletions src/DependencyInjection/LeagueOAuth2ServerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use League\Bundle\OAuth2ServerBundle\Manager\Doctrine\AuthorizationCodeManager;
use League\Bundle\OAuth2ServerBundle\Manager\Doctrine\ClientManager;
use League\Bundle\OAuth2ServerBundle\Manager\Doctrine\RefreshTokenManager;
use League\Bundle\OAuth2ServerBundle\Manager\InMemory\AccessTokenManager as InMemoryAccessTokenManager;
use League\Bundle\OAuth2ServerBundle\Manager\ScopeManagerInterface;
use League\Bundle\OAuth2ServerBundle\Model\Scope as ScopeModel;
use League\Bundle\OAuth2ServerBundle\Persistence\Mapping\Driver;
Expand Down Expand Up @@ -54,6 +55,7 @@ public function load(array $configs, ContainerBuilder $container)

$config = $this->processConfiguration(new Configuration(), $configs);

$this->configureAccessTokenSaving($loader, $config['authorization_server']);
$this->configurePersistence($loader, $container, $config);
$this->configureAuthorizationServer($container, $config['authorization_server']);
$this->configureResourceServer($container, $config['resource_server']);
Expand Down Expand Up @@ -206,6 +208,15 @@ private function configureGrants(ContainerBuilder $container, array $config): vo
;
}

private function configureAccessTokenSaving(LoaderInterface $loader, array $config): void
{
if ($config['persist_access_token']) {
$loader->load('access_token/default.php');
} else {
$loader->load('access_token/null.php');
}
}

/**
* @throws \Exception
*/
Expand All @@ -221,7 +232,7 @@ private function configurePersistence(LoaderInterface $loader, ContainerBuilder
switch ($persistenceMethod) {
case 'in_memory':
$loader->load('storage/in_memory.php');
$this->configureInMemoryPersistence($container);
$this->configureInMemoryPersistence($container, $config);
break;
case 'doctrine':
$loader->load('storage/doctrine.php');
Expand All @@ -241,6 +252,7 @@ private function configureDoctrinePersistence(ContainerBuilder $container, array
$container
->findDefinition(AccessTokenManager::class)
->replaceArgument(0, $entityManager)
->replaceArgument(1, $config['authorization_server']['persist_access_token'])
;

$container
Expand All @@ -267,14 +279,19 @@ private function configureDoctrinePersistence(ContainerBuilder $container, array
$container
->findDefinition(Driver::class)
->replaceArgument(0, $config['client']['classname'])
->replaceArgument(1, $config['authorization_server']['persist_access_token'])
;

$container->setParameter('league.oauth2_server.persistence.doctrine.enabled', true);
$container->setParameter('league.oauth2_server.persistence.doctrine.manager', $entityManagerName);
}

private function configureInMemoryPersistence(ContainerBuilder $container): void
private function configureInMemoryPersistence(ContainerBuilder $container, array $config): void
{
$container
->findDefinition(InMemoryAccessTokenManager::class)
->replaceArgument(0, $config['authorization_server']['persist_access_token'])
;
$container->setParameter('league.oauth2_server.persistence.in_memory.enabled', true);
}

Expand Down
20 changes: 20 additions & 0 deletions src/Manager/InMemory/AccessTokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,41 @@ final class AccessTokenManager implements AccessTokenManagerInterface
*/
private $accessTokens = [];

/** @var bool */
private $persistAccessToken;

public function __construct(bool $persistAccessToken)
{
$this->persistAccessToken = $persistAccessToken;
}

/**
* @psalm-mutation-free
*/
public function find(string $identifier): ?AccessToken
{
if (!$this->persistAccessToken) {
return null;
}

return $this->accessTokens[$identifier] ?? null;
}

public function save(AccessToken $accessToken): void
{
if (!$this->persistAccessToken) {
return;
}

$this->accessTokens[$accessToken->getIdentifier()] = $accessToken;
}

public function clearExpired(): int
{
if (!$this->persistAccessToken) {
return 0;
}

$count = \count($this->accessTokens);

$now = new \DateTimeImmutable();
Expand Down
25 changes: 25 additions & 0 deletions src/Manager/Null/AccessTokenManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace League\Bundle\OAuth2ServerBundle\Manager\Null;

use League\Bundle\OAuth2ServerBundle\Manager\AccessTokenManagerInterface;
use League\Bundle\OAuth2ServerBundle\Model\AccessToken;

final class AccessTokenManager implements AccessTokenManagerInterface
{
public function find(string $identifier): ?AccessToken
{
return null;
}

public function save(AccessToken $accessToken): void
{
}

public function clearExpired(): int
{
return 0;
}
}
20 changes: 15 additions & 5 deletions src/Persistence/Mapping/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ class Driver implements MappingDriver
*/
private $clientClass;

public function __construct(string $clientClass)
/** @var bool */
private $persistAccessToken;

public function __construct(string $clientClass, bool $persistAccessToken)
{
$this->clientClass = $clientClass;
$this->persistAccessToken = $persistAccessToken;
}

public function loadMetadataForClass($className, ClassMetadata $metadata): void
Expand Down Expand Up @@ -63,11 +67,11 @@ public function getAllClassNames(): array
return array_merge(
[
AbstractClient::class,
AccessToken::class,
AuthorizationCode::class,
RefreshToken::class,
],
Client::class === $this->clientClass ? [Client::class] : []
Client::class === $this->clientClass ? [Client::class] : [],
$this->persistAccessToken ? [AccessToken::class] : []
);
}

Expand Down Expand Up @@ -126,12 +130,18 @@ private function buildClientMetadata(ClassMetadata $metadata): void

private function buildRefreshTokenMetadata(ClassMetadata $metadata): void
{
(new ClassMetadataBuilder($metadata))
$classMetadataBuilder = (new ClassMetadataBuilder($metadata))
->setTable('oauth2_refresh_token')
->createField('identifier', 'string')->makePrimaryKey()->length(80)->option('fixed', true)->build()
->addField('expiry', 'datetime_immutable')
->addField('revoked', 'boolean')
->createManyToOne('accessToken', AccessToken::class)->addJoinColumn('access_token', 'identifier', true, false, 'SET NULL')->build()
;

if ($this->persistAccessToken) {
$classMetadataBuilder->createManyToOne('accessToken', AccessToken::class)
->addJoinColumn('access_token', 'identifier', true, false, 'SET NULL')
->build()
;
}
}
}
54 changes: 54 additions & 0 deletions src/Repository/NullAccessTokenRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace League\Bundle\OAuth2ServerBundle\Repository;

use League\Bundle\OAuth2ServerBundle\Entity\AccessToken as AccessTokenEntity;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;

final class NullAccessTokenRepository implements AccessTokenRepositoryInterface
{
/**
* {@inheritdoc}
*/
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null): AccessTokenEntityInterface
{
/** @var int|string|null $userIdentifier */
$accessToken = new AccessTokenEntity();
$accessToken->setClient($clientEntity);
$accessToken->setUserIdentifier($userIdentifier);

foreach ($scopes as $scope) {
$accessToken->addScope($scope);
}

return $accessToken;
}

/**
* {@inheritdoc}
*/
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity): void
{
// do nothing
}

/**
* {@inheritdoc}
*/
public function revokeAccessToken($tokenId): void
{
// do nothing
}

/**
* {@inheritdoc}
*/
public function isAccessTokenRevoked($tokenId): bool
{
return false;
}
}
24 changes: 24 additions & 0 deletions src/Resources/config/access_token/default.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
use League\Bundle\OAuth2ServerBundle\Converter\ScopeConverterInterface;
use League\Bundle\OAuth2ServerBundle\Manager\AccessTokenManagerInterface;
use League\Bundle\OAuth2ServerBundle\Manager\ClientManagerInterface;
use League\Bundle\OAuth2ServerBundle\Repository\AccessTokenRepository;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $container): void {
$container->services()

->set('league.oauth2_server.repository.access_token', AccessTokenRepository::class)
->args([
service(AccessTokenManagerInterface::class),
service(ClientManagerInterface::class),
service(ScopeConverterInterface::class),
])
->alias(AccessTokenRepositoryInterface::class, 'league.oauth2_server.repository.access_token')
->alias(AccessTokenRepository::class, 'league.oauth2_server.repository.access_token');
};
21 changes: 21 additions & 0 deletions src/Resources/config/access_token/null.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

use League\Bundle\OAuth2ServerBundle\Manager\AccessTokenManagerInterface;
use League\Bundle\OAuth2ServerBundle\Manager\Null\AccessTokenManager;
use League\Bundle\OAuth2ServerBundle\Repository\AccessTokenRepository;
use League\Bundle\OAuth2ServerBundle\Repository\NullAccessTokenRepository;
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $container): void {
$container->services()
->set('league.oauth2_server.repository.access_token', NullAccessTokenRepository::class)
->alias(AccessTokenRepositoryInterface::class, 'league.oauth2_server.repository.access_token')
->alias(AccessTokenRepository::class, 'league.oauth2_server.repository.access_token')

->set('league.oauth2_server.manager.null.access_token', AccessTokenManager::class)
->alias(AccessTokenManagerInterface::class, 'league.oauth2_server.manager.null.access_token')
->alias(AccessTokenManager::class, 'league.oauth2_server.manager.null.access_token');
};
10 changes: 0 additions & 10 deletions src/Resources/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
use League\Bundle\OAuth2ServerBundle\Manager\RefreshTokenManagerInterface;
use League\Bundle\OAuth2ServerBundle\Manager\ScopeManagerInterface;
use League\Bundle\OAuth2ServerBundle\OAuth2Events;
use League\Bundle\OAuth2ServerBundle\Repository\AccessTokenRepository;
use League\Bundle\OAuth2ServerBundle\Repository\AuthCodeRepository;
use League\Bundle\OAuth2ServerBundle\Repository\ClientRepository;
use League\Bundle\OAuth2ServerBundle\Repository\RefreshTokenRepository;
Expand Down Expand Up @@ -70,15 +69,6 @@
->alias(ClientRepositoryInterface::class, 'league.oauth2_server.repository.client')
->alias(ClientRepository::class, 'league.oauth2_server.repository.client')

->set('league.oauth2_server.repository.access_token', AccessTokenRepository::class)
->args([
service(AccessTokenManagerInterface::class),
service(ClientManagerInterface::class),
service(ScopeConverterInterface::class),
])
->alias(AccessTokenRepositoryInterface::class, 'league.oauth2_server.repository.access_token')
->alias(AccessTokenRepository::class, 'league.oauth2_server.repository.access_token')

->set('league.oauth2_server.repository.refresh_token', RefreshTokenRepository::class)
->args([
service(RefreshTokenManagerInterface::class),
Expand Down
2 changes: 2 additions & 0 deletions src/Resources/config/storage/doctrine.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
->set('league.oauth2_server.persistence.driver', Driver::class)
->args([
null,
null,
])
->alias(Driver::class, 'league.oauth2_server.persistence.driver')

Expand All @@ -38,6 +39,7 @@
->set('league.oauth2_server.manager.doctrine.access_token', AccessTokenManager::class)
->args([
null,
null,
])
->alias(AccessTokenManagerInterface::class, 'league.oauth2_server.manager.doctrine.access_token')
->alias(AccessTokenManager::class, 'league.oauth2_server.manager.doctrine.access_token')
Expand Down
Loading

0 comments on commit f9f55a9

Please sign in to comment.