Skip to content

fix: #225: GrantConfigurator should accept League\OAuth2\Server\Grant… #227

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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
@@ -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')

85 changes: 85 additions & 0 deletions docs/implementing-custom-grant-type.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,90 @@
# Implementing custom grant type

1. Create a class that implements the `League\OAuth2\Server\Grant\GrantTypeInterface` interface.

Example:

```php
<?php

declare(strict_types=1);

namespace App\Grant;

use DateInterval;
use League\OAuth2\Server\Grant\AbstractGrant;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Nyholm\Psr7\Response;
use Psr\Http\Message\ServerRequestInterface;
use League\OAuth2\Server\Grant\GrantTypeInterface;

final class FakeGrant extends AbstractGrant implements GrantTypeInterface
{
/**
* @var SomeDependency
*/
private $foo;

public function __construct(SomeDependency $foo)
{
$this->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 you prefer php configuration, you could use `AutoconfigureTag` symfony attribute for the same result :

```php
<?php
...

use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;

#[AutoconfigureTag(name: 'league.oauth2_server.authorization_server.grant', attributes: [accessTokenTTL: 'PT5H'])]
final class FakeGrant extends AbstractGrant implements GrantTypeInterface
{
...
}
```

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:
7 changes: 6 additions & 1 deletion src/AuthorizationServer/GrantConfigurator.php
Original file line number Diff line number Diff line change
@@ -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());
}
}
}
}
3 changes: 3 additions & 0 deletions src/AuthorizationServer/GrantTypeInterface.php
Original file line number Diff line number Diff line change
@@ -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;
62 changes: 62 additions & 0 deletions src/DependencyInjection/CompilerPass/GrantTypePass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace League\Bundle\OAuth2ServerBundle\DependencyInjection\CompilerPass;

use League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface;
use League\OAuth2\Server\AuthorizationServer;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

class GrantTypePass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
// check if AuthorizationServer service is defined
if (!$container->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) {
// 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,
]);
}
}
}
}
4 changes: 4 additions & 0 deletions src/DependencyInjection/LeagueOAuth2ServerExtension.php
Original file line number Diff line number Diff line change
@@ -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', [
3 changes: 3 additions & 0 deletions src/LeagueOAuth2ServerBundle.php
Original file line number Diff line number Diff line change
@@ -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
10 changes: 5 additions & 5 deletions tests/Acceptance/TokenEndpointTest.php
Original file line number Diff line number Diff line change
@@ -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']);
7 changes: 1 addition & 6 deletions tests/Fixtures/FakeGrant.php
Original file line number Diff line number Diff line change
@@ -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');
}
}
24 changes: 24 additions & 0 deletions tests/Fixtures/FakeGrantNullAccessTokenTTL.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace League\Bundle\OAuth2ServerBundle\Tests\Fixtures;

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;

final class FakeGrantNullAccessTokenTTL extends AbstractGrant implements GrantTypeInterface
{
public function getIdentifier(): string
{
return self::class;
}

public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, \DateInterval $accessTokenTTL): ResponseTypeInterface
{
return new Response();
}
}
24 changes: 24 additions & 0 deletions tests/Fixtures/FakeGrantUndefinedAccessTokenTTL.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace League\Bundle\OAuth2ServerBundle\Tests\Fixtures;

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;

final class FakeGrantUndefinedAccessTokenTTL extends AbstractGrant implements GrantTypeInterface
{
public function getIdentifier(): string
{
return self::class;
}

public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, \DateInterval $accessTokenTTL): ResponseTypeInterface
{
return new Response();
}
}
33 changes: 33 additions & 0 deletions tests/Fixtures/FakeLegacyGrant.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace League\Bundle\OAuth2ServerBundle\Tests\Fixtures;

use League\Bundle\OAuth2ServerBundle\AuthorizationServer\GrantTypeInterface;
use League\OAuth2\Server\Grant\AbstractGrant;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Nyholm\Psr7\Response;
use Psr\Http\Message\ServerRequestInterface;

// TODO remove code bloc when bundle interface and configurator will be deleted
/**
* @deprecated
*/
final class FakeLegacyGrant extends AbstractGrant implements GrantTypeInterface
{
public function getIdentifier(): string
{
return 'fake_legacy_grant';
}

public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, \DateInterval $accessTokenTTL): ResponseTypeInterface
{
return new Response();
}

public function getAccessTokenTTL(): ?\DateInterval
{
return new \DateInterval('PT5H');
}
}
26 changes: 23 additions & 3 deletions tests/Integration/AuthorizationServerCustomGrantTest.php
Original file line number Diff line number Diff line change
@@ -5,6 +5,9 @@
namespace League\Bundle\OAuth2ServerBundle\Tests\Integration;

use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrant;
use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantNullAccessTokenTTL;
use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeGrantUndefinedAccessTokenTTL;
use League\Bundle\OAuth2ServerBundle\Tests\Fixtures\FakeLegacyGrant;
use League\OAuth2\Server\AuthorizationServer;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

@@ -21,10 +24,27 @@ public function testAuthorizationServerHasOurCustomGrantEnabled(): void
$reflectionProperty = $reflectionClass->getProperty('enabledGrantTypes');
$reflectionProperty->setAccessible(true);

$reflectionTTLProperty = $reflectionClass->getProperty('grantTypeAccessTokenTTL');
$reflectionTTLProperty->setAccessible(true);

$enabledGrantTypes = $reflectionProperty->getValue($authorizationServer);
$grantTypeAccessTokenTTL = $reflectionTTLProperty->getValue($authorizationServer);

$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);

// TODO remove code bloc when bundle interface and configurator will be deleted
$this->assertGrantConfig('fake_legacy_grant', new \DateInterval('PT5H'), $enabledGrantTypes, $grantTypeAccessTokenTTL, FakeLegacyGrant::class);
}

private function assertGrantConfig(string $grantId, ?\DateInterval $accessTokenTTL, array $enabledGrantTypes, array $grantTypeAccessTokenTTL, ?string $grantClass = null): void
{
$grantClass ??= $grantId;

$this->assertArrayHasKey('fake_grant', $enabledGrantTypes);
$this->assertInstanceOf(FakeGrant::class, $enabledGrantTypes['fake_grant']);
$this->assertEquals(new \DateInterval('PT5H'), $enabledGrantTypes['fake_grant']->getAccessTokenTTL());
$this->assertArrayHasKey($grantId, $enabledGrantTypes);
$this->assertInstanceOf($grantClass, $enabledGrantTypes[$grantId]);
$this->assertArrayHasKey($grantId, $grantTypeAccessTokenTTL);
$this->assertEquals($accessTokenTTL, $grantTypeAccessTokenTTL[$grantId]);
}
}
14 changes: 7 additions & 7 deletions tests/Integration/AuthorizationServerTest.php
Original file line number Diff line number Diff line change
@@ -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());
19 changes: 17 additions & 2 deletions tests/TestKernel.php
Original file line number Diff line number Diff line change
@@ -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;
@@ -16,6 +15,9 @@
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\FakeGrantUndefinedAccessTokenTTL;
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;
@@ -168,6 +170,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' => [
@@ -246,7 +249,19 @@ private function configureCustomPersistenceServices(ContainerBuilder $container)

private function registerFakeGrant(ContainerBuilder $container): void
{
$container->register(FakeGrant::class)->setAutoconfigured(true);
$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)
->addTag('league.oauth2_server.authorization_server.grant', ['accessTokenTTL' => null]);

$container->register(FakeGrantUndefinedAccessTokenTTL::class)
->addTag('league.oauth2_server.authorization_server.grant');

// TODO remove line when bundle interface and configurator will be deleted
$container->register(FakeLegacyGrant::class)->setAutoconfigured(true);
}

private function initializeEnvironmentVariables(): void