diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index c537c1ee..99d83fc8 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -10,13 +10,13 @@ jobs: fail-fast: false matrix: php: ['7.4', '8.0', '8.1', '8.2', '8.3'] - symfony: ['4.4.*', '5.4.*', '6.0.*', '6.1.*', '6.2.*', '6.3.*', '6.4.*', '7.0.*'] + symfony: ['5.4.*', '6.0.*', '6.1.*', '6.2.*', '6.3.*', '6.4.*', '7.0.*'] composer-flags: ['--prefer-stable'] can-fail: [false] extensions: ['curl, iconv, mbstring, mongodb, pdo, pdo_sqlite, sqlite, zip'] include: - php: '7.4' - symfony: '4.4.*' + symfony: '5.4.*' composer-flags: '--prefer-stable --prefer-lowest' can-fail: false extensions: 'curl, iconv, mbstring, mongodb, pdo, pdo_sqlite, sqlite, zip' diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 3c2b2d37..2b7e0a24 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -12,7 +12,6 @@ namespace Gesdinet\JWTRefreshTokenBundle\DependencyInjection; use Gesdinet\JWTRefreshTokenBundle\Entity\RefreshToken; -use Symfony\Component\Config\Definition\BaseNode; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; @@ -34,15 +33,15 @@ public function getConfigTreeBuilder(): TreeBuilder ->info('The default update TTL flag for all authenticators.') ->end() ->scalarNode('firewall') - ->setDeprecated(...$this->getDeprecationParameters('The "%node%" node is deprecated without replacement.', '1.0')) + ->setDeprecated('gesdinet/jwt-refresh-token-bundle', '1.0', 'The "%node%" node is deprecated without replacement.') ->defaultValue('api') ->end() ->scalarNode('user_provider') - ->setDeprecated(...$this->getDeprecationParameters('The "%node%" node is deprecated without replacement.', '1.0')) + ->setDeprecated('gesdinet/jwt-refresh-token-bundle', '1.0', 'The "%node%" node is deprecated without replacement.') ->defaultNull() ->end() ->scalarNode('user_identity_field') - ->setDeprecated(...$this->getDeprecationParameters('The "%node%" node is deprecated without replacement.', '1.0')) + ->setDeprecated('gesdinet/jwt-refresh-token-bundle', '1.0', 'The "%node%" node is deprecated without replacement.') ->defaultValue('username') ->end() ->scalarNode('manager_type') @@ -68,16 +67,16 @@ public function getConfigTreeBuilder(): TreeBuilder ->info('Set the object manager to use (default: doctrine.orm.entity_manager)') ->end() ->scalarNode('user_checker') - ->setDeprecated(...$this->getDeprecationParameters('The "%node%" node is deprecated without replacement.', '1.0')) + ->setDeprecated('gesdinet/jwt-refresh-token-bundle', '1.0', 'The "%node%" node is deprecated without replacement.') ->defaultValue('security.user_checker') ->end() ->scalarNode('refresh_token_entity') - ->setDeprecated(...$this->getDeprecationParameters('The "%node%" node is deprecated, use the "refresh_token_class" node instead.', '0.5')) + ->setDeprecated('gesdinet/jwt-refresh-token-bundle', '0.5', 'The "%node%" node is deprecated, use the "refresh_token_class" node instead.') ->defaultNull() ->info(sprintf('Set the refresh token class to use (default: %s)', RefreshToken::class)) ->end() ->scalarNode('entity_manager') - ->setDeprecated(...$this->getDeprecationParameters('The "%node%" node is deprecated, use the "object_manager" node instead.', '0.5')) + ->setDeprecated('gesdinet/jwt-refresh-token-bundle', '0.5', 'The "%node%" node is deprecated, use the "object_manager" node instead.') ->defaultNull() ->info('Set the entity manager to use') ->end() @@ -90,7 +89,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->info('The default request parameter name containing the refresh token for all authenticators.') ->end() ->booleanNode('doctrine_mappings') - ->setDeprecated(...$this->getDeprecationParameters('The "%node%" node is deprecated without replacement.', '1.0')) + ->setDeprecated('gesdinet/jwt-refresh-token-bundle', '1.0', 'The "%node%" node is deprecated without replacement.') ->info('When true, resolving of Doctrine mapping is done automatically to use either ORM or ODM object manager') ->defaultTrue() ->end() @@ -125,13 +124,4 @@ public function getConfigTreeBuilder(): TreeBuilder return $treeBuilder; } - - private function getDeprecationParameters(string $message, string $version): array - { - if (method_exists(BaseNode::class, 'getDeprecation')) { - return ['gesdinet/jwt-refresh-token-bundle', $version, $message]; - } - - return [$message]; - } } diff --git a/GesdinetJWTRefreshTokenBundle.php b/GesdinetJWTRefreshTokenBundle.php index b9da63a3..ad50675e 100644 --- a/GesdinetJWTRefreshTokenBundle.php +++ b/GesdinetJWTRefreshTokenBundle.php @@ -10,7 +10,6 @@ use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; -use Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface; class GesdinetJWTRefreshTokenBundle extends Bundle { @@ -23,11 +22,8 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new ObjectManagerCompilerPass()); $container->addCompilerPass(new UserCheckerCompilerPass(true)); - // Only register the security authenticator for Symfony 5.4+ - if (interface_exists(RememberMeHandlerInterface::class)) { - /** @var SecurityExtension $extension */ - $extension = $container->getExtension('security'); - $extension->addAuthenticatorFactory(new RefreshTokenAuthenticatorFactory()); - } + /** @var SecurityExtension $extension */ + $extension = $container->getExtension('security'); + $extension->addAuthenticatorFactory(new RefreshTokenAuthenticatorFactory()); } } diff --git a/README.md b/README.md index 78ba93d6..5a494064 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ The purpose of this bundle is manage refresh tokens with JWT (Json Web Tokens) i ## Prerequisites -This bundle requires PHP 7.4 or later and Symfony 4.4, 5.4, or 6.0+. +This bundle requires PHP 7.4 or later and Symfony 5.4 or later. For support with older Symfony versions, please use the 0.12 release. @@ -25,7 +25,7 @@ For support with older Symfony versions, please use the 0.12 release. **You must also install either the Doctrine ORM or MongoDB ODM, these packages are not installed automatically with this bundle. Failing to do so may trigger errors on installation.** -If using Symfony 4.4, you will also need to install the `symfony/security-guard` package, it is only required for the legacy authentication API and is not compatible with Symfony 6.0. +If using Symfony 5.4 with the deprecated Guard authenticators, you will also need to install the `symfony/security-guard` package. Note that it is only required for the legacy authentication API and is not compatible with Symfony 6.0. With Doctrine's ORM @@ -177,7 +177,7 @@ security: # ... ``` -### Step 4 (Symfony 4.4) +### Step 4 (Symfony 5.4 with Guard Authentication) #### Define the refresh token route @@ -319,7 +319,7 @@ security: By default, when a user provider is not specified, then the user provider for the firewall is used instead. -#### Symfony 4.4 +#### Symfony 5.4 with Guard Authentication *NOTE* This setting is deprecated and is not used with the `refresh_jwt` authenticator @@ -365,7 +365,7 @@ security: refresh_jwt: ~ ``` -#### Symfony 4.4 +#### Symfony 5.4 with Guard Authentication *NOTE* This setting is deprecated and is not used with the `refresh_jwt` authenticator diff --git a/Resources/config/services.php b/Resources/config/services.php index ebfe6943..736dc2fc 100644 --- a/Resources/config/services.php +++ b/Resources/config/services.php @@ -1,5 +1,7 @@ services(); $services->set('gesdinet.jwtrefreshtoken.send_token') ->class(AttachRefreshTokenOnSuccessListener::class) ->args([ - new Reference('gesdinet.jwtrefreshtoken.refresh_token_manager'), - new Parameter('gesdinet_jwt_refresh_token.ttl'), - new Reference('request_stack'), - new Parameter('gesdinet_jwt_refresh_token.token_parameter_name'), - new Parameter('gesdinet_jwt_refresh_token.single_use'), - new Reference('gesdinet.jwtrefreshtoken.refresh_token_generator'), - new Reference('gesdinet.jwtrefreshtoken.request.extractor.chain'), - new Parameter('gesdinet_jwt_refresh_token.cookie'), - new Parameter('gesdinet_jwt_refresh_token.return_expiration'), - new Parameter('gesdinet_jwt_refresh_token.return_expiration_parameter_name'), + service('gesdinet.jwtrefreshtoken.refresh_token_manager'), + param('gesdinet_jwt_refresh_token.ttl'), + service('request_stack'), + param('gesdinet_jwt_refresh_token.token_parameter_name'), + param('gesdinet_jwt_refresh_token.single_use'), + service('gesdinet.jwtrefreshtoken.refresh_token_generator'), + service('gesdinet.jwtrefreshtoken.request.extractor.chain'), + param('gesdinet_jwt_refresh_token.cookie'), + param('gesdinet_jwt_refresh_token.return_expiration'), + param('gesdinet_jwt_refresh_token.return_expiration_parameter_name'), ]) ->tag('kernel.event_listener', [ 'event' => 'lexik_jwt_authentication.on_authentication_success', @@ -66,7 +48,7 @@ ->class(RefreshTokenGenerator::class) ->public() ->args([ - new Reference('gesdinet.jwtrefreshtoken.refresh_token_manager'), + service('gesdinet.jwtrefreshtoken.refresh_token_manager'), ]); $services->alias(RefreshTokenGeneratorInterface::class, 'gesdinet.jwtrefreshtoken.refresh_token_generator'); @@ -75,8 +57,8 @@ ->class(RefreshTokenManager::class) ->public() ->args([ - new Reference('gesdinet.jwtrefreshtoken.object_manager'), - new Parameter('gesdinet.jwtrefreshtoken.refresh_token.class'), + service('gesdinet.jwtrefreshtoken.object_manager'), + param('gesdinet.jwtrefreshtoken.refresh_token.class'), ]); $services->alias(RefreshTokenManagerInterface::class, 'gesdinet.jwtrefreshtoken.refresh_token_manager'); @@ -100,83 +82,83 @@ ->tag('gesdinet_jwt_refresh_token.request_extractor'); $services->set('gesdinet.jwtrefreshtoken') - ->deprecate(...$deprecateArgs('1.0')) + ->deprecate('gesdinet/jwt-refresh-token-bundle', '1.0', 'The "%service_id%" service is deprecated.') ->class(RefreshToken::class) ->public() ->args([ - new Reference('gesdinet.jwtrefreshtoken.authenticator'), - new Reference('gesdinet.jwtrefreshtoken.user_provider'), - new Reference('lexik_jwt_authentication.handler.authentication_success'), - new Reference('lexik_jwt_authentication.handler.authentication_failure'), - new Reference('gesdinet.jwtrefreshtoken.refresh_token_manager'), - new Parameter('gesdinet_jwt_refresh_token.ttl'), - new Parameter('gesdinet_jwt_refresh_token.security.firewall'), - new Parameter('gesdinet_jwt_refresh_token.ttl_update'), - new Reference('event_dispatcher'), + service('gesdinet.jwtrefreshtoken.authenticator'), + service('gesdinet.jwtrefreshtoken.user_provider'), + service('lexik_jwt_authentication.handler.authentication_success'), + service('lexik_jwt_authentication.handler.authentication_failure'), + service('gesdinet.jwtrefreshtoken.refresh_token_manager'), + param('gesdinet_jwt_refresh_token.ttl'), + param('gesdinet_jwt_refresh_token.security.firewall'), + param('gesdinet_jwt_refresh_token.ttl_update'), + service('event_dispatcher'), ]); $services->set('gesdinet.jwtrefreshtoken.user_provider') - ->deprecate(...$deprecateArgs('1.0')) + ->deprecate('gesdinet/jwt-refresh-token-bundle', '1.0', 'The "%service_id%" service is deprecated.') ->class(RefreshTokenProvider::class) ->args([ - new Reference('gesdinet.jwtrefreshtoken.refresh_token_manager'), + service('gesdinet.jwtrefreshtoken.refresh_token_manager'), ]); $services->set('gesdinet.jwtrefreshtoken.authenticator') - ->deprecate(...$deprecateArgs('1.0')) + ->deprecate('gesdinet/jwt-refresh-token-bundle', '1.0', 'The "%service_id%" service is deprecated.') ->class(LegacyRefreshTokenAuthenticator::class) ->args([ - new Reference('gesdinet.jwtrefreshtoken.user_checker'), - new Parameter('gesdinet_jwt_refresh_token.token_parameter_name'), - new Reference('gesdinet.jwtrefreshtoken.request.extractor.chain'), + service('gesdinet.jwtrefreshtoken.user_checker'), + param('gesdinet_jwt_refresh_token.token_parameter_name'), + service('gesdinet.jwtrefreshtoken.request.extractor.chain'), ]); $services->set('gesdinet.jwtrefreshtoken.security.authentication.failure_handler') ->class(AuthenticationFailureHandler::class) ->args([ - new Reference('event_dispatcher'), + service('event_dispatcher'), ]); $services->set('gesdinet.jwtrefreshtoken.security.authentication.success_handler') ->class(AuthenticationSuccessHandler::class) ->args([ - new Reference('lexik_jwt_authentication.handler.authentication_success'), - new Reference('event_dispatcher'), + service('lexik_jwt_authentication.handler.authentication_success'), + service('event_dispatcher'), ]); $services->set('gesdinet.jwtrefreshtoken.security.refresh_token_authenticator') ->abstract() ->class(RefreshTokenAuthenticator::class) ->args([ - new Reference('gesdinet.jwtrefreshtoken.refresh_token_manager'), - new Reference('event_dispatcher'), - new Reference('gesdinet.jwtrefreshtoken.request.extractor.chain'), - $abstractArg('user provider'), - $abstractArg('authentication success handler'), - $abstractArg('authentication failure handler'), - $abstractArg('options'), - new Reference('security.http_utils'), + service('gesdinet.jwtrefreshtoken.refresh_token_manager'), + service('event_dispatcher'), + service('gesdinet.jwtrefreshtoken.request.extractor.chain'), + abstract_arg('user provider'), + abstract_arg('authentication success handler'), + abstract_arg('authentication failure handler'), + abstract_arg('options'), + service('security.http_utils'), ]); $services->set(ClearInvalidRefreshTokensCommand::class) ->args([ - new Reference('gesdinet.jwtrefreshtoken.refresh_token_manager'), + service('gesdinet.jwtrefreshtoken.refresh_token_manager'), ]) ->tag('console.command'); $services->set(RevokeRefreshTokenCommand::class) ->args([ - new Reference('gesdinet.jwtrefreshtoken.refresh_token_manager'), + service('gesdinet.jwtrefreshtoken.refresh_token_manager'), ]) ->tag('console.command'); $services->set(LogoutEventListener::class) ->args([ - new Reference('gesdinet.jwtrefreshtoken.refresh_token_manager'), - new Reference('gesdinet.jwtrefreshtoken.request.extractor.chain'), - new Parameter('gesdinet_jwt_refresh_token.token_parameter_name'), - new Parameter('gesdinet_jwt_refresh_token.cookie'), - new Parameter('gesdinet_jwt_refresh_token.logout_firewall_context'), + service('gesdinet.jwtrefreshtoken.refresh_token_manager'), + service('gesdinet.jwtrefreshtoken.request.extractor.chain'), + param('gesdinet_jwt_refresh_token.token_parameter_name'), + param('gesdinet_jwt_refresh_token.cookie'), + param('gesdinet_jwt_refresh_token.logout_firewall_context'), ]) ->tag('kernel.event_listener', [ 'event' => 'Symfony\Component\Security\Http\Event\LogoutEvent', diff --git a/Tests/Functional/DependencyInjection/Security/Factory/RefreshTokenAuthenticatorFactoryTest.php b/Tests/Functional/DependencyInjection/Security/Factory/RefreshTokenAuthenticatorFactoryTest.php index 3051f8bf..b32c7f11 100644 --- a/Tests/Functional/DependencyInjection/Security/Factory/RefreshTokenAuthenticatorFactoryTest.php +++ b/Tests/Functional/DependencyInjection/Security/Factory/RefreshTokenAuthenticatorFactoryTest.php @@ -7,7 +7,6 @@ use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\Security\Http\RememberMe\RememberMeHandlerInterface; final class RefreshTokenAuthenticatorFactoryTest extends TestCase { @@ -21,13 +20,6 @@ final class RefreshTokenAuthenticatorFactoryTest extends TestCase */ private $container; - public static function setUpBeforeClass(): void - { - if (!interface_exists(RememberMeHandlerInterface::class)) { - self::markTestSkipped('Only applies to Symfony 5.3+'); - } - } - protected function setUp(): void { $this->factory = new RefreshTokenAuthenticatorFactory(); diff --git a/composer.json b/composer.json index 0ddba9df..21bd6a59 100644 --- a/composer.json +++ b/composer.json @@ -16,18 +16,18 @@ "php": ">=7.4", "doctrine/persistence": "^1.3.3|^2.0|^3.0", "lexik/jwt-authentication-bundle": "^2.0|^3.0", - "symfony/config": "^4.4|^5.4|^6.0|^7.0", - "symfony/console": "^4.4|^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^4.4|^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/deprecation-contracts": "^2.1|^3.0", - "symfony/event-dispatcher": "^4.4|^5.4|^6.0|^7.0", - "symfony/http-foundation": "^4.4|^5.4|^6.0|^7.0", - "symfony/http-kernel": "^4.4|^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", "symfony/polyfill-php80": "^1.15", - "symfony/property-access": "^4.4|^5.4|^6.0|^7.0", - "symfony/security-bundle": "^4.4|^5.4|^6.0|^7.0", - "symfony/security-core": "^4.4|^5.4|^6.0|^7.0", - "symfony/security-http": "^4.4|^5.4|^6.0|^7.0" + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/security-bundle": "^5.4|^6.0|^7.0", + "symfony/security-core": "^5.4|^6.0|^7.0", + "symfony/security-http": "^5.4|^6.0|^7.0" }, "require-dev": { "doctrine/annotations": "^1.13|^2.0", @@ -37,8 +37,8 @@ "matthiasnoback/symfony-config-test": "^4.2|^5.0", "matthiasnoback/symfony-dependency-injection-test": "^4.2|^5.0", "phpunit/phpunit": "^9.5", - "symfony/cache": "^4.4|^5.4|^6.0|^7.0", - "symfony/security-guard": "^4.4|^5.4" + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/security-guard": "^5.4" }, "conflict": { "doctrine/mongodb-odm": "<2.2",