From c88895f6119af6c748bedc076fbfab95a4e0f20d Mon Sep 17 00:00:00 2001 From: Gildas de Cadoudal Date: Sun, 23 Mar 2025 17:41:44 +0100 Subject: [PATCH 1/6] fix: #225: GrantConfigurator should accept League\OAuth2\Server\Grant\GrantTypeInterface --- config/services.php | 2 + docs/implementing-custom-grant-type.md | 70 +++++++++++++++++++ src/AuthorizationServer/GrantConfigurator.php | 7 +- .../GrantTypeInterface.php | 3 + .../CompilerPass/GrantTypePass.php | 59 ++++++++++++++++ .../LeagueOAuth2ServerExtension.php | 4 ++ src/LeagueOAuth2ServerBundle.php | 3 + tests/Fixtures/FakeGrant.php | 7 +- tests/Fixtures/FakeLegacyGrant.php | 33 +++++++++ .../AuthorizationServerCustomGrantTest.php | 13 +++- tests/TestKernel.php | 6 +- 11 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 src/DependencyInjection/CompilerPass/GrantTypePass.php create mode 100644 tests/Fixtures/FakeLegacyGrant.php diff --git a/config/services.php b/config/services.php index be416c4f..c3888188 100644 --- a/config/services.php +++ b/config/services.php @@ -133,6 +133,7 @@ ->set('league.oauth2_server.emitter', EventEmitter::class) ->call('subscribeListenersFrom', [service('league.oauth2_server.symfony_league_listener_provider')]) + // TODO remove code bloc when bundle interface and configurator will be deleted ->set('league.oauth2_server.authorization_server.grant_configurator', GrantConfigurator::class) ->args([ tagged_iterator('league.oauth2_server.authorization_server.grant'), @@ -150,6 +151,7 @@ null, ]) ->call('setEmitter', [service('league.oauth2_server.emitter')]) + // TODO remove next line when bundle interface and configurator will be deleted ->configurator(service(GrantConfigurator::class)) ->alias(AuthorizationServer::class, 'league.oauth2_server.authorization_server') diff --git a/docs/implementing-custom-grant-type.md b/docs/implementing-custom-grant-type.md index e890137b..eeb30441 100644 --- a/docs/implementing-custom-grant-type.md +++ b/docs/implementing-custom-grant-type.md @@ -1,5 +1,75 @@ # Implementing custom grant type +1. Create a class that implements the `League\OAuth2\Server\Grant\GrantTypeInterface` interface. + + Example: + + ```php + foo = $foo; + } + + public function getIdentifier() + { + return 'fake_grant'; + } + + public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, DateInterval $accessTokenTTL) + { + return new Response(); + } + } + ``` + +1. In order to enable the new grant type in the authorization server you must register the service in the container. +And the service must be tagged with the `league.oauth2_server.authorization_server.grant` tag: + + ```yaml + services: + + App\Grant\FakeGrant: + tags: + - {name: league.oauth2_server.authorization_server.grant} + ``` + + You could define a custom access token TTL for your grant using `accessTokenTTL` tag attribute : + + ```yaml + services: + + App\Grant\FakeGrant: + tags: + - {name: league.oauth2_server.authorization_server.grant, accessTokenTTL: PT5H} + ``` + + If `accessTokenTTL` tag attribute is not defined, then bundle config is used `league_oauth2_server.authorization_server.access_token_ttl` (same as `league.oauth2_server.access_token_ttl.default` service container parameter). \ + `null` is considered as defined, to allow to unset ttl. \ + `league_oauth2_server.authorization_server.refresh_token_ttl` is also accessible for your implementation using `league.oauth2_server.refresh_token_ttl.default` service container parameter. + + +# Implementing custom grant type (deprecated method) + 1. Create a class that implements the `\League\Bundle\OAuth2ServerBundle\League\AuthorizationServer\GrantTypeInterface` interface. Example: diff --git a/src/AuthorizationServer/GrantConfigurator.php b/src/AuthorizationServer/GrantConfigurator.php index e6d9762a..430c2252 100644 --- a/src/AuthorizationServer/GrantConfigurator.php +++ b/src/AuthorizationServer/GrantConfigurator.php @@ -6,6 +6,9 @@ use League\OAuth2\Server\AuthorizationServer; +/** + * @deprecated + */ final class GrantConfigurator { /** @@ -24,7 +27,9 @@ public function __construct(iterable $grants) public function __invoke(AuthorizationServer $authorizationServer): void { foreach ($this->grants as $grant) { - $authorizationServer->enableGrantType($grant, $grant->getAccessTokenTTL()); + if ($grant instanceof GrantTypeInterface) { + $authorizationServer->enableGrantType($grant, $grant->getAccessTokenTTL()); + } } } } diff --git a/src/AuthorizationServer/GrantTypeInterface.php b/src/AuthorizationServer/GrantTypeInterface.php index 93df05ae..8e181644 100644 --- a/src/AuthorizationServer/GrantTypeInterface.php +++ b/src/AuthorizationServer/GrantTypeInterface.php @@ -6,6 +6,9 @@ use League\OAuth2\Server\Grant\GrantTypeInterface as LeagueGrantTypeInterface; +/** + * @deprecated use League\OAuth2\Server\Grant\GrantTypeInterface with accessTokenTTL tag attribute instead + */ interface GrantTypeInterface extends LeagueGrantTypeInterface { public function getAccessTokenTTL(): ?\DateInterval; diff --git a/src/DependencyInjection/CompilerPass/GrantTypePass.php b/src/DependencyInjection/CompilerPass/GrantTypePass.php new file mode 100644 index 00000000..886eeedf --- /dev/null +++ b/src/DependencyInjection/CompilerPass/GrantTypePass.php @@ -0,0 +1,59 @@ +has(AuthorizationServer::class)) { + return; + } + + $definition = $container->findDefinition(AuthorizationServer::class); + + // find all service IDs with the league.oauth2_server.authorization_server.grant tag + $taggedServices = $container->findTaggedServiceIds('league.oauth2_server.authorization_server.grant'); + + // enable grant type for each + foreach ($taggedServices as $id => $tags) { + // skip of custom grant using \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface + // since there are handled by \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantConfigurator + // TODO remove code bloc when bundle interface and configurator will be deleted + try { + $grantDefinition = $container->findDefinition($id); + /** @var class-string|null $grantClass */ + $grantClass = $grantDefinition->getClass(); + if (null !== $grantClass) { + $refGrantClass = new \ReflectionClass($grantClass); + if ($refGrantClass->implementsInterface(GrantTypeInterface::class)) { + continue; + } + } + } catch (\ReflectionException) { + // handling of this service as native one + } + + foreach ($tags as $attributes) { + $definition->addMethodCall('enableGrantType', [ + new Reference($id), + // use accessTokenTTL tag attribute if exists, otherwise use global bundle config + new Definition(\DateInterval::class, [\array_key_exists('accessTokenTTL', $attributes) + ? $attributes['accessTokenTTL'] + : $container->getParameter('league.oauth2_server.access_token_ttl.default')]), + ]); + } + } + } +} diff --git a/src/DependencyInjection/LeagueOAuth2ServerExtension.php b/src/DependencyInjection/LeagueOAuth2ServerExtension.php index edcb8f1a..b1427d99 100644 --- a/src/DependencyInjection/LeagueOAuth2ServerExtension.php +++ b/src/DependencyInjection/LeagueOAuth2ServerExtension.php @@ -69,6 +69,7 @@ public function load(array $configs, ContainerBuilder $container) $container->findDefinition(OAuth2Authenticator::class) ->setArgument(3, $config['role_prefix']); + // TODO remove code bloc when bundle interface and configurator will be deleted $container->registerForAutoconfiguration(GrantTypeInterface::class) ->addTag('league.oauth2_server.authorization_server.grant'); @@ -139,6 +140,7 @@ private function configureAuthorizationServer(ContainerBuilder $container, array { $container->setParameter('league.oauth2_server.encryption_key', $config['encryption_key']); $container->setParameter('league.oauth2_server.encryption_key.type', $config['encryption_key_type']); + $container->setParameter('league.oauth2_server.access_token_ttl.default', $config['access_token_ttl']); $authorizationServer = $container ->findDefinition(AuthorizationServer::class) @@ -199,6 +201,8 @@ private function configureAuthorizationServer(ContainerBuilder $container, array */ private function configureGrants(ContainerBuilder $container, array $config): void { + $container->setParameter('league.oauth2_server.refresh_token_ttl.default', $config['refresh_token_ttl']); + $container ->findDefinition(PasswordGrant::class) ->addMethodCall('setRefreshTokenTTL', [ diff --git a/src/LeagueOAuth2ServerBundle.php b/src/LeagueOAuth2ServerBundle.php index 0478860b..3146e2cf 100644 --- a/src/LeagueOAuth2ServerBundle.php +++ b/src/LeagueOAuth2ServerBundle.php @@ -6,6 +6,7 @@ use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass; use League\Bundle\OAuth2ServerBundle\DependencyInjection\CompilerPass\EncryptionKeyPass; +use League\Bundle\OAuth2ServerBundle\DependencyInjection\CompilerPass\GrantTypePass; use League\Bundle\OAuth2ServerBundle\DependencyInjection\LeagueOAuth2ServerExtension; use League\Bundle\OAuth2ServerBundle\DependencyInjection\Security\OAuth2Factory; use League\Bundle\OAuth2ServerBundle\Persistence\Mapping\Driver; @@ -26,6 +27,8 @@ public function build(ContainerBuilder $container) $this->configureDoctrineExtension($container); $this->configureSecurityExtension($container); + + $container->addCompilerPass(new GrantTypePass()); } public function getContainerExtension(): ExtensionInterface diff --git a/tests/Fixtures/FakeGrant.php b/tests/Fixtures/FakeGrant.php index 04216f4a..1efe71a0 100644 --- a/tests/Fixtures/FakeGrant.php +++ b/tests/Fixtures/FakeGrant.php @@ -4,8 +4,8 @@ namespace League\Bundle\OAuth2ServerBundle\Tests\Fixtures; -use League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface; use League\OAuth2\Server\Grant\AbstractGrant; +use League\OAuth2\Server\Grant\GrantTypeInterface; use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; use Nyholm\Psr7\Response; use Psr\Http\Message\ServerRequestInterface; @@ -21,9 +21,4 @@ public function respondToAccessTokenRequest(ServerRequestInterface $request, Res { return new Response(); } - - public function getAccessTokenTTL(): ?\DateInterval - { - return new \DateInterval('PT5H'); - } } diff --git a/tests/Fixtures/FakeLegacyGrant.php b/tests/Fixtures/FakeLegacyGrant.php new file mode 100644 index 00000000..64cf5def --- /dev/null +++ b/tests/Fixtures/FakeLegacyGrant.php @@ -0,0 +1,33 @@ +getProperty('enabledGrantTypes'); $reflectionProperty->setAccessible(true); + $reflectionTTLProperty = $reflectionClass->getProperty('grantTypeAccessTokenTTL'); + $reflectionTTLProperty->setAccessible(true); + $enabledGrantTypes = $reflectionProperty->getValue($authorizationServer); + $grantTypeAccessTokenTTL = $reflectionTTLProperty->getValue($authorizationServer); $this->assertArrayHasKey('fake_grant', $enabledGrantTypes); $this->assertInstanceOf(FakeGrant::class, $enabledGrantTypes['fake_grant']); - $this->assertEquals(new \DateInterval('PT5H'), $enabledGrantTypes['fake_grant']->getAccessTokenTTL()); + $this->assertArrayHasKey('fake_grant', $grantTypeAccessTokenTTL); + $this->assertEquals(new \DateInterval('PT5H'), $grantTypeAccessTokenTTL['fake_grant']); + + // TODO remove code bloc when bundle interface and configurator will be deleted + $this->assertArrayHasKey('fake_legacy_grant', $enabledGrantTypes); + $this->assertInstanceOf(FakeLegacyGrant::class, $enabledGrantTypes['fake_legacy_grant']); + $this->assertEquals(new \DateInterval('PT5H'), $enabledGrantTypes['fake_legacy_grant']->getAccessTokenTTL()); } } diff --git a/tests/TestKernel.php b/tests/TestKernel.php index 889a1030..e83b86ca 100644 --- a/tests/TestKernel.php +++ b/tests/TestKernel.php @@ -16,6 +16,7 @@ use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeClientManager; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeCredentialsRevoker; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrant; +use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeLegacyGrant; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeRefreshTokenManager; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FixtureFactory; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\SecurityTestController; @@ -246,7 +247,10 @@ private function configureCustomPersistenceServices(ContainerBuilder $container) private function registerFakeGrant(ContainerBuilder $container): void { - $container->register(FakeGrant::class)->setAutoconfigured(true); + $container->register(FakeGrant::class) + ->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => 'PT5H']); + // TODO remove line when bundle interface and configurator will be deleted + $container->register(FakeLegacyGrant::class)->setAutoconfigured(true); } private function initializeEnvironmentVariables(): void From 0ffa8062a3acb91c2db5bbb8eaa60a8a6555a3f9 Mon Sep 17 00:00:00 2001 From: Gildas de Cadoudal Date: Sun, 23 Mar 2025 18:20:15 +0100 Subject: [PATCH 2/6] fix: #225: coding standards --- src/DependencyInjection/CompilerPass/GrantTypePass.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/DependencyInjection/CompilerPass/GrantTypePass.php b/src/DependencyInjection/CompilerPass/GrantTypePass.php index 886eeedf..9f162875 100644 --- a/src/DependencyInjection/CompilerPass/GrantTypePass.php +++ b/src/DependencyInjection/CompilerPass/GrantTypePass.php @@ -1,4 +1,6 @@ - Date: Sun, 23 Mar 2025 18:57:27 +0100 Subject: [PATCH 3/6] fix: #225: update documentation to add usage of AutoconfigureTag attribute --- docs/implementing-custom-grant-type.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/implementing-custom-grant-type.md b/docs/implementing-custom-grant-type.md index eeb30441..df30e896 100644 --- a/docs/implementing-custom-grant-type.md +++ b/docs/implementing-custom-grant-type.md @@ -63,6 +63,21 @@ And the service must be tagged with the `league.oauth2_server.authorization_serv - {name: league.oauth2_server.authorization_server.grant, accessTokenTTL: PT5H} ``` + If you prefer php configuration, you could use `AutoconfigureTag` symfony attribute for the same result : + + ```php + Date: Mon, 24 Mar 2025 10:54:42 +0100 Subject: [PATCH 4/6] fix: #225: register for autoconfiguration of League\OAuth2\Server\Grant\GrantTypeInterface --- docs/implementing-custom-grant-type.md | 42 ++++++++++++++++-- src/Attribute/WithAccessTokenTTL.php | 12 +++++ .../CompilerPass/GrantTypePass.php | 44 +++++++++++++------ .../LeagueOAuth2ServerExtension.php | 4 ++ tests/Acceptance/TokenEndpointTest.php | 10 ++--- .../Fixtures/FakeGrantNullAccessTokenTTL.php | 24 ++++++++++ ...keGrantNullAccessTokenTTLWithAttribute.php | 26 +++++++++++ .../FakeGrantUndefinedAccessTokenTTL.php | 24 ++++++++++ ...efinedAccessTokenTTLOnlyAutoconfigured.php | 24 ++++++++++ tests/Fixtures/FakeGrantWithAttribute.php | 26 +++++++++++ .../AuthorizationServerCustomGrantTest.php | 30 ++++++++++--- tests/Integration/AuthorizationServerTest.php | 14 +++--- tests/TestKernel.php | 23 +++++++++- 13 files changed, 265 insertions(+), 38 deletions(-) create mode 100644 src/Attribute/WithAccessTokenTTL.php create mode 100644 tests/Fixtures/FakeGrantNullAccessTokenTTL.php create mode 100644 tests/Fixtures/FakeGrantNullAccessTokenTTLWithAttribute.php create mode 100644 tests/Fixtures/FakeGrantUndefinedAccessTokenTTL.php create mode 100644 tests/Fixtures/FakeGrantUndefinedAccessTokenTTLOnlyAutoconfigured.php create mode 100644 tests/Fixtures/FakeGrantWithAttribute.php diff --git a/docs/implementing-custom-grant-type.md b/docs/implementing-custom-grant-type.md index df30e896..218466b6 100644 --- a/docs/implementing-custom-grant-type.md +++ b/docs/implementing-custom-grant-type.md @@ -43,7 +43,9 @@ ``` 1. In order to enable the new grant type in the authorization server you must register the service in the container. -And the service must be tagged with the `league.oauth2_server.authorization_server.grant` tag: +`\League\OAuth2\Server\Grant\GrantTypeInterface` is registered for autoconfiguration + + - but you can manually declare the service with the `league.oauth2_server.authorization_server.grant` tag: ```yaml services: @@ -53,7 +55,24 @@ And the service must be tagged with the `league.oauth2_server.authorization_serv - {name: league.oauth2_server.authorization_server.grant} ``` - You could define a custom access token TTL for your grant using `accessTokenTTL` tag attribute : + - If you prefer php configuration, you could use `AutoconfigureTag` symfony attribute for the same result : + + ```php + $tags) { - // skip of custom grant using \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface - // since there are handled by \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantConfigurator - // TODO remove code bloc when bundle interface and configurator will be deleted + // we only use the first tag + // this allow to override autoregistration of interface to be able to set accessTokenTTL + // since autoregistered tag are defined in last + $attributes = array_shift($tags); + try { $grantDefinition = $container->findDefinition($id); /** @var class-string|null $grantClass */ $grantClass = $grantDefinition->getClass(); if (null !== $grantClass) { $refGrantClass = new \ReflectionClass($grantClass); + + // skip of custom grant using \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface + // since there are handled by \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantConfigurator + // TODO remove code bloc when bundle interface and configurator will be deleted if ($refGrantClass->implementsInterface(GrantTypeInterface::class)) { continue; } + + // read of accessTokenTTL from WithAccessTokenTTL attribute + $withAccessTokenTTLAttributes = $refGrantClass->getAttributes(WithAccessTokenTTL::class); + if (count($withAccessTokenTTLAttributes) > 0) { + // we only use first attribute, because WithAccessTokenTTL is not repeatable + /** @var \ReflectionAttribute $withAccessTokenTTLAttribute */ + $withAccessTokenTTLAttributeArguments = array_shift($withAccessTokenTTLAttributes)->getArguments(); + $attributes['accessTokenTTL'] = array_shift($withAccessTokenTTLAttributeArguments); + } } } catch (\ReflectionException) { - // handling of this service as native one + // handling of this service as native one or without attribute } - foreach ($tags as $attributes) { - $definition->addMethodCall('enableGrantType', [ - new Reference($id), - // use accessTokenTTL tag attribute if exists, otherwise use global bundle config - new Definition(\DateInterval::class, [\array_key_exists('accessTokenTTL', $attributes) - ? $attributes['accessTokenTTL'] - : $container->getParameter('league.oauth2_server.access_token_ttl.default')]), - ]); - } + // use WithAccessTokenTTL value then accessTokenTTL tag attribute if exists, otherwise use global bundle config + $accessTokenTTLValue = \array_key_exists('accessTokenTTL', $attributes) + ? $attributes['accessTokenTTL'] + : $container->getParameter('league.oauth2_server.access_token_ttl.default'); + + $definition->addMethodCall('enableGrantType', [ + new Reference($id), + (is_string($accessTokenTTLValue)) + ? new Definition(\DateInterval::class, [$accessTokenTTLValue]) + : $accessTokenTTLValue, + ]); } } } diff --git a/src/DependencyInjection/LeagueOAuth2ServerExtension.php b/src/DependencyInjection/LeagueOAuth2ServerExtension.php index b1427d99..1ab3bf67 100644 --- a/src/DependencyInjection/LeagueOAuth2ServerExtension.php +++ b/src/DependencyInjection/LeagueOAuth2ServerExtension.php @@ -31,6 +31,7 @@ use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\Grant\AuthCodeGrant; use League\OAuth2\Server\Grant\ClientCredentialsGrant; +use League\OAuth2\Server\Grant\GrantTypeInterface as LeagueGrantTypeInterface; use League\OAuth2\Server\Grant\ImplicitGrant; use League\OAuth2\Server\Grant\PasswordGrant; use League\OAuth2\Server\Grant\RefreshTokenGrant; @@ -69,6 +70,9 @@ public function load(array $configs, ContainerBuilder $container) $container->findDefinition(OAuth2Authenticator::class) ->setArgument(3, $config['role_prefix']); + $container->registerForAutoconfiguration(LeagueGrantTypeInterface::class) + ->addTag('league.oauth2_server.authorization_server.grant'); + // TODO remove code bloc when bundle interface and configurator will be deleted $container->registerForAutoconfiguration(GrantTypeInterface::class) ->addTag('league.oauth2_server.authorization_server.grant'); diff --git a/tests/Acceptance/TokenEndpointTest.php b/tests/Acceptance/TokenEndpointTest.php index 5f586714..64d5f7cf 100644 --- a/tests/Acceptance/TokenEndpointTest.php +++ b/tests/Acceptance/TokenEndpointTest.php @@ -63,7 +63,7 @@ public function testSuccessfulClientCredentialsRequest(): void $jsonResponse = json_decode($response->getContent(), true); $this->assertSame('Bearer', $jsonResponse['token_type']); - $this->assertLessThanOrEqual(3600, $jsonResponse['expires_in']); + $this->assertLessThanOrEqual(7200, $jsonResponse['expires_in']); $this->assertGreaterThan(0, $jsonResponse['expires_in']); $this->assertNotEmpty($jsonResponse['access_token']); $this->assertArrayNotHasKey('refresh_token', $jsonResponse); @@ -118,7 +118,7 @@ public function testSuccessfulPasswordRequest(): void $jsonResponse = json_decode($response->getContent(), true); $this->assertSame('Bearer', $jsonResponse['token_type']); - $this->assertLessThanOrEqual(3600, $jsonResponse['expires_in']); + $this->assertLessThanOrEqual(7200, $jsonResponse['expires_in']); $this->assertGreaterThan(0, $jsonResponse['expires_in']); $this->assertNotEmpty($jsonResponse['access_token']); $this->assertNotEmpty($jsonResponse['refresh_token']); @@ -184,7 +184,7 @@ public function testSuccessfulRefreshTokenRequest(): void $jsonResponse = json_decode($response->getContent(), true); $this->assertSame('Bearer', $jsonResponse['token_type']); - $this->assertLessThanOrEqual(3600, $jsonResponse['expires_in']); + $this->assertLessThanOrEqual(7200, $jsonResponse['expires_in']); $this->assertGreaterThan(0, $jsonResponse['expires_in']); $this->assertNotEmpty($jsonResponse['access_token']); $this->assertNotEmpty($jsonResponse['refresh_token']); @@ -228,7 +228,7 @@ public function testSuccessfulAuthorizationCodeRequest(): void $jsonResponse = json_decode($response->getContent(), true); $this->assertSame('Bearer', $jsonResponse['token_type']); - $this->assertLessThanOrEqual(3600, $jsonResponse['expires_in']); + $this->assertLessThanOrEqual(7200, $jsonResponse['expires_in']); $this->assertGreaterThan(0, $jsonResponse['expires_in']); $this->assertNotEmpty($jsonResponse['access_token']); $this->assertEmpty($response->headers->get('foo'), 'bar'); @@ -277,7 +277,7 @@ public function testSuccessfulAuthorizationCodeRequestWithPublicClient(): void $jsonResponse = json_decode($response->getContent(), true); $this->assertSame('Bearer', $jsonResponse['token_type']); - $this->assertLessThanOrEqual(3600, $jsonResponse['expires_in']); + $this->assertLessThanOrEqual(7200, $jsonResponse['expires_in']); $this->assertGreaterThan(0, $jsonResponse['expires_in']); $this->assertNotEmpty($jsonResponse['access_token']); $this->assertNotEmpty($jsonResponse['refresh_token']); diff --git a/tests/Fixtures/FakeGrantNullAccessTokenTTL.php b/tests/Fixtures/FakeGrantNullAccessTokenTTL.php new file mode 100644 index 00000000..24fc45e0 --- /dev/null +++ b/tests/Fixtures/FakeGrantNullAccessTokenTTL.php @@ -0,0 +1,24 @@ +getValue($authorizationServer); $grantTypeAccessTokenTTL = $reflectionTTLProperty->getValue($authorizationServer); - $this->assertArrayHasKey('fake_grant', $enabledGrantTypes); - $this->assertInstanceOf(FakeGrant::class, $enabledGrantTypes['fake_grant']); - $this->assertArrayHasKey('fake_grant', $grantTypeAccessTokenTTL); - $this->assertEquals(new \DateInterval('PT5H'), $grantTypeAccessTokenTTL['fake_grant']); + $this->assertGrantConfig('fake_grant', new \DateInterval('PT5H'), $enabledGrantTypes, $grantTypeAccessTokenTTL, FakeGrant::class); + $this->assertGrantConfig(FakeGrantNullAccessTokenTTL::class, new \DateInterval('PT1H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); + $this->assertGrantConfig(FakeGrantUndefinedAccessTokenTTL::class, new \DateInterval('PT2H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); + + $this->assertGrantConfig(FakeGrantWithAttribute::class, new \DateInterval('PT5H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); + $this->assertGrantConfig(FakeGrantNullAccessTokenTTLWithAttribute::class, new \DateInterval('PT1H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); + $this->assertGrantConfig(FakeGrantUndefinedAccessTokenTTLOnlyAutoconfigured::class, new \DateInterval('PT2H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); // TODO remove code bloc when bundle interface and configurator will be deleted - $this->assertArrayHasKey('fake_legacy_grant', $enabledGrantTypes); - $this->assertInstanceOf(FakeLegacyGrant::class, $enabledGrantTypes['fake_legacy_grant']); - $this->assertEquals(new \DateInterval('PT5H'), $enabledGrantTypes['fake_legacy_grant']->getAccessTokenTTL()); + $this->assertGrantConfig('fake_legacy_grant', new \DateInterval('PT5H'), $enabledGrantTypes, $grantTypeAccessTokenTTL, FakeLegacyGrant::class); + } + + private function assertGrantConfig(string $grantId, \DateInterval|null $accessTokenTTL, array $enabledGrantTypes, array $grantTypeAccessTokenTTL, string|null $grantClass = null): void + { + $grantClass ??= $grantId; + + $this->assertArrayHasKey($grantId, $enabledGrantTypes); + $this->assertInstanceOf($grantClass, $enabledGrantTypes[$grantId]); + $this->assertArrayHasKey($grantId, $grantTypeAccessTokenTTL); + $this->assertEquals($accessTokenTTL, $grantTypeAccessTokenTTL[$grantId]); } } diff --git a/tests/Integration/AuthorizationServerTest.php b/tests/Integration/AuthorizationServerTest.php index 88bae9be..e4ab57a4 100644 --- a/tests/Integration/AuthorizationServerTest.php +++ b/tests/Integration/AuthorizationServerTest.php @@ -176,7 +176,7 @@ public function testValidClientCredentialsGrant(): void // Response assertions. $this->assertSame('Bearer', $response['token_type']); - $this->assertLessThanOrEqual(3600, $response['expires_in']); + $this->assertLessThanOrEqual(7200, $response['expires_in']); $this->assertGreaterThan(0, $response['expires_in']); $this->assertInstanceOf(AccessToken::class, $accessToken); @@ -197,7 +197,7 @@ public function testValidClientCredentialsGrantWithScope(): void // Response assertions. $this->assertSame('Bearer', $response['token_type']); - $this->assertLessThanOrEqual(3600, $response['expires_in']); + $this->assertLessThanOrEqual(7200, $response['expires_in']); $this->assertGreaterThan(0, $response['expires_in']); $this->assertInstanceOf(AccessToken::class, $accessToken); @@ -224,7 +224,7 @@ public function testValidClientCredentialsGrantWithInheritedScope(): void // Response assertions. $this->assertSame('Bearer', $response['token_type']); - $this->assertLessThanOrEqual(3600, $response['expires_in']); + $this->assertLessThanOrEqual(7200, $response['expires_in']); $this->assertGreaterThan(0, $response['expires_in']); $this->assertInstanceOf(AccessToken::class, $accessToken); @@ -252,7 +252,7 @@ public function testValidClientCredentialsGrantWithRequestedScope(): void // Response assertions. $this->assertSame('Bearer', $response['token_type']); - $this->assertLessThanOrEqual(3600, $response['expires_in']); + $this->assertLessThanOrEqual(7200, $response['expires_in']); $this->assertGreaterThan(0, $response['expires_in']); $this->assertInstanceOf(AccessToken::class, $accessToken); @@ -286,7 +286,7 @@ public function testValidPasswordGrant(): void // Response assertions. $this->assertSame('Bearer', $response['token_type']); - $this->assertLessThanOrEqual(3600, $response['expires_in']); + $this->assertLessThanOrEqual(7200, $response['expires_in']); $this->assertGreaterThan(0, $response['expires_in']); $this->assertInstanceOf(AccessToken::class, $accessToken); $this->assertInstanceOf(RefreshToken::class, $refreshToken); @@ -361,7 +361,7 @@ public function testValidRefreshGrant(): void // Response assertions. $this->assertSame('Bearer', $response['token_type']); - $this->assertLessThanOrEqual(3600, $response['expires_in']); + $this->assertLessThanOrEqual(7200, $response['expires_in']); $this->assertGreaterThan(0, $response['expires_in']); $this->assertInstanceOf(AccessToken::class, $accessToken); $this->assertInstanceOf(RefreshToken::class, $refreshToken); @@ -645,7 +645,7 @@ public function testSuccessfulAuthorizationWithCode(): void $accessToken = $this->getAccessToken($response['access_token']); $this->assertSame('Bearer', $response['token_type']); - $this->assertLessThanOrEqual(3600, $response['expires_in']); + $this->assertLessThanOrEqual(7200, $response['expires_in']); $this->assertGreaterThan(0, $response['expires_in']); $this->assertInstanceOf(AccessToken::class, $accessToken); $this->assertSame('foo', $accessToken->getClient()->getIdentifier()); diff --git a/tests/TestKernel.php b/tests/TestKernel.php index e83b86ca..6874b027 100644 --- a/tests/TestKernel.php +++ b/tests/TestKernel.php @@ -16,6 +16,11 @@ use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeClientManager; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeCredentialsRevoker; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrant; +use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantNullAccessTokenTTL; +use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantNullAccessTokenTTLWithAttribute; +use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantUndefinedAccessTokenTTL; +use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantUndefinedAccessTokenTTLOnlyAutoconfigured; +use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantWithAttribute; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeLegacyGrant; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeRefreshTokenManager; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FixtureFactory; @@ -169,6 +174,7 @@ public function registerContainerConfiguration(LoaderInterface $loader): void 'authorization_server' => [ 'private_key' => '%env(PRIVATE_KEY_PATH)%', 'encryption_key' => '%env(ENCRYPTION_KEY)%', + 'access_token_ttl' => 'PT2H' // to have a different value as league/oauth2-server lib ], 'resource_server' => $this->resourceServiceConfig ?? ['public_key' => '%env(PUBLIC_KEY_PATH)%'], 'scopes' => [ @@ -247,8 +253,21 @@ private function configureCustomPersistenceServices(ContainerBuilder $container) private function registerFakeGrant(ContainerBuilder $container): void { - $container->register(FakeGrant::class) - ->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => 'PT5H']); + $container->register(FakeGrant::class)->setAutoconfigured(true) + // tagged twice to test this case, only first one is used + ->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => 'PT5H']) + ->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => 'PT3H']); + + $container->register(FakeGrantNullAccessTokenTTL::class)->setAutoconfigured(true) + ->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => null]); + + $container->register(FakeGrantUndefinedAccessTokenTTL::class)->setAutoconfigured(true) + ->addTag('league.oauth2_server.authorization_server.grant'); + + $container->register(FakeGrantWithAttribute::class)->setAutoconfigured(true); + $container->register(FakeGrantNullAccessTokenTTLWithAttribute::class)->setAutoconfigured(true); + $container->register(FakeGrantUndefinedAccessTokenTTLOnlyAutoconfigured::class)->setAutoconfigured(true); + // TODO remove line when bundle interface and configurator will be deleted $container->register(FakeLegacyGrant::class)->setAutoconfigured(true); } From 41caa907baf747590b4588b3fcce93241e97f332 Mon Sep 17 00:00:00 2001 From: Gildas de Cadoudal Date: Mon, 31 Mar 2025 09:17:43 +0200 Subject: [PATCH 5/6] fix: #225: coding standard & stan --- src/Attribute/WithAccessTokenTTL.php | 6 ++++-- src/DependencyInjection/CompilerPass/GrantTypePass.php | 5 ++--- tests/Integration/AuthorizationServerCustomGrantTest.php | 2 +- tests/TestKernel.php | 3 +-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Attribute/WithAccessTokenTTL.php b/src/Attribute/WithAccessTokenTTL.php index b1ce1602..a79f9541 100644 --- a/src/Attribute/WithAccessTokenTTL.php +++ b/src/Attribute/WithAccessTokenTTL.php @@ -1,4 +1,6 @@ -getAttributes(WithAccessTokenTTL::class); - if (count($withAccessTokenTTLAttributes) > 0) { + if (\count($withAccessTokenTTLAttributes) > 0) { // we only use first attribute, because WithAccessTokenTTL is not repeatable - /** @var \ReflectionAttribute $withAccessTokenTTLAttribute */ $withAccessTokenTTLAttributeArguments = array_shift($withAccessTokenTTLAttributes)->getArguments(); $attributes['accessTokenTTL'] = array_shift($withAccessTokenTTLAttributeArguments); } @@ -67,7 +66,7 @@ public function process(ContainerBuilder $container): void $definition->addMethodCall('enableGrantType', [ new Reference($id), - (is_string($accessTokenTTLValue)) + (\is_string($accessTokenTTLValue)) ? new Definition(\DateInterval::class, [$accessTokenTTLValue]) : $accessTokenTTLValue, ]); diff --git a/tests/Integration/AuthorizationServerCustomGrantTest.php b/tests/Integration/AuthorizationServerCustomGrantTest.php index 10bede08..c462bf6c 100644 --- a/tests/Integration/AuthorizationServerCustomGrantTest.php +++ b/tests/Integration/AuthorizationServerCustomGrantTest.php @@ -45,7 +45,7 @@ public function testAuthorizationServerHasOurCustomGrantEnabled(): void $this->assertGrantConfig('fake_legacy_grant', new \DateInterval('PT5H'), $enabledGrantTypes, $grantTypeAccessTokenTTL, FakeLegacyGrant::class); } - private function assertGrantConfig(string $grantId, \DateInterval|null $accessTokenTTL, array $enabledGrantTypes, array $grantTypeAccessTokenTTL, string|null $grantClass = null): void + private function assertGrantConfig(string $grantId, ?\DateInterval $accessTokenTTL, array $enabledGrantTypes, array $grantTypeAccessTokenTTL, ?string $grantClass = null): void { $grantClass ??= $grantId; diff --git a/tests/TestKernel.php b/tests/TestKernel.php index 6874b027..3c86b606 100644 --- a/tests/TestKernel.php +++ b/tests/TestKernel.php @@ -5,7 +5,6 @@ namespace League\Bundle\OAuth2ServerBundle\Tests; use Doctrine\DBAL\Platforms\SqlitePlatform; -use Doctrine\ORM\Mapping\Annotation; use League\Bundle\OAuth2ServerBundle\Manager\AccessTokenManagerInterface; use League\Bundle\OAuth2ServerBundle\Manager\AuthorizationCodeManagerInterface; use League\Bundle\OAuth2ServerBundle\Manager\ClientManagerInterface; @@ -174,7 +173,7 @@ public function registerContainerConfiguration(LoaderInterface $loader): void 'authorization_server' => [ 'private_key' => '%env(PRIVATE_KEY_PATH)%', 'encryption_key' => '%env(ENCRYPTION_KEY)%', - 'access_token_ttl' => 'PT2H' // to have a different value as league/oauth2-server lib + 'access_token_ttl' => 'PT2H', // to have a different value as league/oauth2-server lib ], 'resource_server' => $this->resourceServiceConfig ?? ['public_key' => '%env(PUBLIC_KEY_PATH)%'], 'scopes' => [ From 0975ab8a5fce4eb5e5b86eb71def8b93636878ee Mon Sep 17 00:00:00 2001 From: Gildas de Cadoudal Date: Mon, 31 Mar 2025 11:05:47 +0200 Subject: [PATCH 6/6] fix: #225: revert autoconfiguration of League\OAuth2\Server\Grant\GrantTypeInterface --- docs/implementing-custom-grant-type.md | 42 ++--------------- src/Attribute/WithAccessTokenTTL.php | 14 ------ .../CompilerPass/GrantTypePass.php | 47 +++++++------------ .../LeagueOAuth2ServerExtension.php | 4 -- ...keGrantNullAccessTokenTTLWithAttribute.php | 26 ---------- ...efinedAccessTokenTTLOnlyAutoconfigured.php | 24 ---------- tests/Fixtures/FakeGrantWithAttribute.php | 26 ---------- .../AuthorizationServerCustomGrantTest.php | 9 +--- tests/TestKernel.php | 15 ++---- 9 files changed, 26 insertions(+), 181 deletions(-) delete mode 100644 src/Attribute/WithAccessTokenTTL.php delete mode 100644 tests/Fixtures/FakeGrantNullAccessTokenTTLWithAttribute.php delete mode 100644 tests/Fixtures/FakeGrantUndefinedAccessTokenTTLOnlyAutoconfigured.php delete mode 100644 tests/Fixtures/FakeGrantWithAttribute.php diff --git a/docs/implementing-custom-grant-type.md b/docs/implementing-custom-grant-type.md index 218466b6..df30e896 100644 --- a/docs/implementing-custom-grant-type.md +++ b/docs/implementing-custom-grant-type.md @@ -43,9 +43,7 @@ ``` 1. In order to enable the new grant type in the authorization server you must register the service in the container. -`\League\OAuth2\Server\Grant\GrantTypeInterface` is registered for autoconfiguration - - - but you can manually declare the service with the `league.oauth2_server.authorization_server.grant` tag: +And the service must be tagged with the `league.oauth2_server.authorization_server.grant` tag: ```yaml services: @@ -55,24 +53,7 @@ - {name: league.oauth2_server.authorization_server.grant} ``` - - If you prefer php configuration, you could use `AutoconfigureTag` symfony attribute for the same result : - - ```php - $tags) { - // we only use the first tag - // this allow to override autoregistration of interface to be able to set accessTokenTTL - // since autoregistered tag are defined in last - $attributes = array_shift($tags); - + // skip of custom grant using \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface + // since there are handled by \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantConfigurator + // TODO remove code bloc when bundle interface and configurator will be deleted try { $grantDefinition = $container->findDefinition($id); /** @var class-string|null $grantClass */ $grantClass = $grantDefinition->getClass(); if (null !== $grantClass) { $refGrantClass = new \ReflectionClass($grantClass); - - // skip of custom grant using \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface - // since there are handled by \League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantConfigurator - // TODO remove code bloc when bundle interface and configurator will be deleted if ($refGrantClass->implementsInterface(GrantTypeInterface::class)) { continue; } - - // read of accessTokenTTL from WithAccessTokenTTL attribute - $withAccessTokenTTLAttributes = $refGrantClass->getAttributes(WithAccessTokenTTL::class); - if (\count($withAccessTokenTTLAttributes) > 0) { - // we only use first attribute, because WithAccessTokenTTL is not repeatable - $withAccessTokenTTLAttributeArguments = array_shift($withAccessTokenTTLAttributes)->getArguments(); - $attributes['accessTokenTTL'] = array_shift($withAccessTokenTTLAttributeArguments); - } } } catch (\ReflectionException) { - // handling of this service as native one or without attribute + // handling of this service as native one } - // use WithAccessTokenTTL value then accessTokenTTL tag attribute if exists, otherwise use global bundle config - $accessTokenTTLValue = \array_key_exists('accessTokenTTL', $attributes) - ? $attributes['accessTokenTTL'] - : $container->getParameter('league.oauth2_server.access_token_ttl.default'); - - $definition->addMethodCall('enableGrantType', [ - new Reference($id), - (\is_string($accessTokenTTLValue)) - ? new Definition(\DateInterval::class, [$accessTokenTTLValue]) - : $accessTokenTTLValue, - ]); + foreach ($tags as $attributes) { + // use accessTokenTTL tag attribute if exists, otherwise use global bundle config + $accessTokenTTLValue = \array_key_exists('accessTokenTTL', $attributes) + ? $attributes['accessTokenTTL'] + : $container->getParameter('league.oauth2_server.access_token_ttl.default'); + + $definition->addMethodCall('enableGrantType', [ + new Reference($id), + (\is_string($accessTokenTTLValue)) + ? new Definition(\DateInterval::class, [$accessTokenTTLValue]) + : $accessTokenTTLValue, + ]); + } } } } diff --git a/src/DependencyInjection/LeagueOAuth2ServerExtension.php b/src/DependencyInjection/LeagueOAuth2ServerExtension.php index 1ab3bf67..b1427d99 100644 --- a/src/DependencyInjection/LeagueOAuth2ServerExtension.php +++ b/src/DependencyInjection/LeagueOAuth2ServerExtension.php @@ -31,7 +31,6 @@ use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\Grant\AuthCodeGrant; use League\OAuth2\Server\Grant\ClientCredentialsGrant; -use League\OAuth2\Server\Grant\GrantTypeInterface as LeagueGrantTypeInterface; use League\OAuth2\Server\Grant\ImplicitGrant; use League\OAuth2\Server\Grant\PasswordGrant; use League\OAuth2\Server\Grant\RefreshTokenGrant; @@ -70,9 +69,6 @@ public function load(array $configs, ContainerBuilder $container) $container->findDefinition(OAuth2Authenticator::class) ->setArgument(3, $config['role_prefix']); - $container->registerForAutoconfiguration(LeagueGrantTypeInterface::class) - ->addTag('league.oauth2_server.authorization_server.grant'); - // TODO remove code bloc when bundle interface and configurator will be deleted $container->registerForAutoconfiguration(GrantTypeInterface::class) ->addTag('league.oauth2_server.authorization_server.grant'); diff --git a/tests/Fixtures/FakeGrantNullAccessTokenTTLWithAttribute.php b/tests/Fixtures/FakeGrantNullAccessTokenTTLWithAttribute.php deleted file mode 100644 index 7b50df5d..00000000 --- a/tests/Fixtures/FakeGrantNullAccessTokenTTLWithAttribute.php +++ /dev/null @@ -1,26 +0,0 @@ -getValue($authorizationServer); $grantTypeAccessTokenTTL = $reflectionTTLProperty->getValue($authorizationServer); - $this->assertGrantConfig('fake_grant', new \DateInterval('PT5H'), $enabledGrantTypes, $grantTypeAccessTokenTTL, FakeGrant::class); + $this->assertGrantConfig('fake_grant', new \DateInterval('PT3H'), $enabledGrantTypes, $grantTypeAccessTokenTTL, FakeGrant::class); $this->assertGrantConfig(FakeGrantNullAccessTokenTTL::class, new \DateInterval('PT1H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); $this->assertGrantConfig(FakeGrantUndefinedAccessTokenTTL::class, new \DateInterval('PT2H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); - $this->assertGrantConfig(FakeGrantWithAttribute::class, new \DateInterval('PT5H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); - $this->assertGrantConfig(FakeGrantNullAccessTokenTTLWithAttribute::class, new \DateInterval('PT1H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); - $this->assertGrantConfig(FakeGrantUndefinedAccessTokenTTLOnlyAutoconfigured::class, new \DateInterval('PT2H'), $enabledGrantTypes, $grantTypeAccessTokenTTL); - // TODO remove code bloc when bundle interface and configurator will be deleted $this->assertGrantConfig('fake_legacy_grant', new \DateInterval('PT5H'), $enabledGrantTypes, $grantTypeAccessTokenTTL, FakeLegacyGrant::class); } diff --git a/tests/TestKernel.php b/tests/TestKernel.php index 3c86b606..3430e8eb 100644 --- a/tests/TestKernel.php +++ b/tests/TestKernel.php @@ -16,10 +16,7 @@ use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeCredentialsRevoker; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrant; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantNullAccessTokenTTL; -use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantNullAccessTokenTTLWithAttribute; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantUndefinedAccessTokenTTL; -use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantUndefinedAccessTokenTTLOnlyAutoconfigured; -use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantWithAttribute; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeLegacyGrant; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeRefreshTokenManager; use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FixtureFactory; @@ -252,21 +249,17 @@ private function configureCustomPersistenceServices(ContainerBuilder $container) private function registerFakeGrant(ContainerBuilder $container): void { - $container->register(FakeGrant::class)->setAutoconfigured(true) - // tagged twice to test this case, only first one is used + $container->register(FakeGrant::class) + // tagged twice to test this case, last one win ->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => 'PT5H']) ->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => 'PT3H']); - $container->register(FakeGrantNullAccessTokenTTL::class)->setAutoconfigured(true) + $container->register(FakeGrantNullAccessTokenTTL::class) ->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => null]); - $container->register(FakeGrantUndefinedAccessTokenTTL::class)->setAutoconfigured(true) + $container->register(FakeGrantUndefinedAccessTokenTTL::class) ->addTag('league.oauth2_server.authorization_server.grant'); - $container->register(FakeGrantWithAttribute::class)->setAutoconfigured(true); - $container->register(FakeGrantNullAccessTokenTTLWithAttribute::class)->setAutoconfigured(true); - $container->register(FakeGrantUndefinedAccessTokenTTLOnlyAutoconfigured::class)->setAutoconfigured(true); - // TODO remove line when bundle interface and configurator will be deleted $container->register(FakeLegacyGrant::class)->setAutoconfigured(true); }