From 9cefec521ca5fd38b96f59e3c2813d2897507099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20J=2E=20Garc=C3=ADa=20Lagar?= Date: Mon, 13 Oct 2025 19:04:35 +0200 Subject: [PATCH 1/4] Allow testing against `doctrine/doctrine-bundle:^3.0` --- composer.json | 2 +- tests/TestKernel.php | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index fbc3f13..a96e142 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "require-dev": { "ext-pdo": "*", "ext-pdo_sqlite": "*", - "doctrine/doctrine-bundle": "^2.8.0", + "doctrine/doctrine-bundle": "^2.8|^3.0", "doctrine/orm": "^2.14|^3.0", "symfony/browser-kit": "^6.4|^7.0", "symfony/phpunit-bridge": "^7.2" diff --git a/tests/TestKernel.php b/tests/TestKernel.php index c25870f..a53d931 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; @@ -90,8 +89,7 @@ public function registerContainerConfiguration(LoaderInterface $loader): void ], ]; - $doctrine['orm'] = ['enable_lazy_ghost_objects' => !interface_exists(Annotation::class)]; - + $doctrine['orm'] = []; $container->loadFromExtension('doctrine', $doctrine); $framework = [ From 92e8101e2368f1f76df2a2f053f88bb8e002ce35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20J=2E=20Garc=C3=ADa=20Lagar?= Date: Tue, 16 Sep 2025 12:11:37 +0200 Subject: [PATCH 2/4] Add support for Symfony 8 --- .github/workflows/unit-tests.yml | 5 +++++ composer.json | 14 +++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index e08f130..c0dc1b7 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -25,6 +25,11 @@ jobs: doctrine-orm: "^2.14" composer-flags: '--prefer-stable --prefer-lowest' can-fail: false + - php: "8.4" + symfony: "8.0.*" + doctrine-orm: "^3.0" + composer-flags: '' + can-fail: true exclude: - php: "8.1" symfony: "7.1.*" diff --git a/composer.json b/composer.json index a96e142..9c6b4b3 100644 --- a/composer.json +++ b/composer.json @@ -22,19 +22,19 @@ "nyholm/psr7": "^1.4", "psr/http-factory": "^1.0", "symfony/deprecation-contracts": "^3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/filesystem": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/psr-http-message-bridge": "^6.4|^7", - "symfony/security-bundle": "^6.4|^7.0" + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/psr-http-message-bridge": "^6.4|^7.0|^8.0", + "symfony/security-bundle": "^6.4|^7.0|^8.0" }, "require-dev": { "ext-pdo": "*", "ext-pdo_sqlite": "*", "doctrine/doctrine-bundle": "^2.8|^3.0", "doctrine/orm": "^2.14|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/phpunit-bridge": "^7.2" + "symfony/browser-kit": "^6.4|^7.0|^8.0", + "symfony/phpunit-bridge": "^7.3" }, "conflict": { "doctrine/doctrine-bundle": "<2.8.0", From 07712408e0ef5a75974be1bc16196195f03171e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20J=2E=20Garc=C3=ADa=20Lagar?= Date: Wed, 15 Oct 2025 12:08:36 +0200 Subject: [PATCH 3/4] Add missing `void` return types --- .../LeagueOAuth2ServerExtension.php | 14 +++----------- src/LeagueOAuth2ServerBundle.php | 5 +---- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/DependencyInjection/LeagueOAuth2ServerExtension.php b/src/DependencyInjection/LeagueOAuth2ServerExtension.php index 03750dd..9b77bbf 100644 --- a/src/DependencyInjection/LeagueOAuth2ServerExtension.php +++ b/src/DependencyInjection/LeagueOAuth2ServerExtension.php @@ -49,11 +49,9 @@ final class LeagueOAuth2ServerExtension extends Extension implements PrependExtensionInterface, CompilerPassInterface { /** - * @return void - * * @throws \Exception */ - public function load(array $configs, ContainerBuilder $container) + public function load(array $configs, ContainerBuilder $container): void { $loader = new PhpFileLoader($container, new FileLocator(__DIR__ . '/../../config')); $loader->load('services.php'); @@ -90,10 +88,7 @@ public function getAlias(): string return 'league_oauth2_server'; } - /** - * @return void - */ - public function prepend(ContainerBuilder $container) + public function prepend(ContainerBuilder $container): void { // If no doctrine connection is configured, the DBAL connection should // be left alone as adding any configuration setting with no connection @@ -114,10 +109,7 @@ public function prepend(ContainerBuilder $container) ]); } - /** - * @return void - */ - public function process(ContainerBuilder $container) + public function process(ContainerBuilder $container): void { $this->assertRequiredBundlesAreEnabled($container); } diff --git a/src/LeagueOAuth2ServerBundle.php b/src/LeagueOAuth2ServerBundle.php index 050b906..6d714f1 100644 --- a/src/LeagueOAuth2ServerBundle.php +++ b/src/LeagueOAuth2ServerBundle.php @@ -17,10 +17,7 @@ final class LeagueOAuth2ServerBundle extends Bundle { - /** - * @return void - */ - public function build(ContainerBuilder $container) + public function build(ContainerBuilder $container): void { parent::build($container); From dc89d463985f40f5f553e70103bf82b781307c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20J=2E=20Garc=C3=ADa=20Lagar?= Date: Wed, 15 Oct 2025 12:25:59 +0200 Subject: [PATCH 4/4] Prevent empty userIdentifier --- .../Authenticator/OAuth2Authenticator.php | 15 ++++++++++++++- tests/Unit/OAuth2AuthenticatorTest.php | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Security/Authenticator/OAuth2Authenticator.php b/src/Security/Authenticator/OAuth2Authenticator.php index d986633..270f049 100644 --- a/src/Security/Authenticator/OAuth2Authenticator.php +++ b/src/Security/Authenticator/OAuth2Authenticator.php @@ -16,6 +16,8 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\User\AttributesBasedUserProviderInterface; +use Symfony\Component\Security\Core\User\ChainUserProvider; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface; @@ -70,6 +72,14 @@ public function authenticate(Request $request): Passport /** @var string $userIdentifier */ $userIdentifier = $psr7Request->getAttribute('oauth_user_id', ''); + if ('' === $userIdentifier) { + /** + * BC layer for Symfony < 8.0 + */ + if (is_a(ChainUserProvider::class, AttributesBasedUserProviderInterface::class, true)) { + throw OAuth2AuthenticationFailedException::create('The access token has either an empty or missing "oauth_user_id" attribute.'); + } + } /** @var string $accessTokenId */ $accessTokenId = $psr7Request->getAttribute('oauth_access_token_id'); @@ -81,7 +91,10 @@ public function authenticate(Request $request): Passport $oauthClientId = $psr7Request->getAttribute('oauth_client_id', ''); $userLoader = function (string $userIdentifier) use ($oauthClientId): UserInterface { - if ('' === $userIdentifier || $oauthClientId === $userIdentifier) { + if ( + $oauthClientId === $userIdentifier + || ('' === $userIdentifier && is_a(ChainUserProvider::class, AttributesBasedUserProviderInterface::class, true)) // BC layer for Symfony < 8.0 + ) { return new ClientCredentialsUser($oauthClientId); } diff --git a/tests/Unit/OAuth2AuthenticatorTest.php b/tests/Unit/OAuth2AuthenticatorTest.php index 80e30d9..f8f94b9 100644 --- a/tests/Unit/OAuth2AuthenticatorTest.php +++ b/tests/Unit/OAuth2AuthenticatorTest.php @@ -97,6 +97,8 @@ public function testAuthenticateCreatePassportWithClientCredentialsUser(): void { $serverRequest = (new ServerRequest('GET', '/foo')) ->withAttribute('oauth_access_token_id', 'accessTokenId') + ->withAttribute('oauth_user_id', 'clientId') + ->withAttribute('oauth_client_id', 'clientId') ; $httpMessageFactory = $this->createMock(HttpMessageFactoryInterface::class);