From e011b0f1227771e0f006f98ad1e908ae908ef565 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Fri, 27 Jun 2025 19:54:16 +0200 Subject: [PATCH] [SecurityBundle] Remove deprecated OIDC token handler options `algorithm` and `key` --- UPGRADE-8.0.md | 15 ++++ .../Bundle/SecurityBundle/CHANGELOG.md | 1 + .../AccessToken/OidcTokenHandlerFactory.php | 39 +-------- .../Factory/AccessTokenFactoryTest.php | 86 +------------------ .../app/AccessToken/config_oidc_jwe.yml | 2 +- 5 files changed, 20 insertions(+), 123 deletions(-) diff --git a/UPGRADE-8.0.md b/UPGRADE-8.0.md index b7cecbc258426..29c9a740a57c7 100644 --- a/UPGRADE-8.0.md +++ b/UPGRADE-8.0.md @@ -398,6 +398,21 @@ SecurityBundle - `'account_status'`: A new option that only exposes account status errors (e.g., account locked, disabled) * Make `ExpressionCacheWarmer` class `final` + * Remove the deprecated `algorithm` and `key` options from the OIDC token handler configuration, use `algorithms` and `keyset` instead + + ```diff + # config/packages/security.yaml + security: + firewalls: + main: + access_token: + token_handler: + oidc: + - algorithm: 'RS256' + - key: 'https://example.com/.well-known/jwks.json' + + algorithms: ['RS256'] + + keyset: 'https://example.com/.well-known/jwks.json' + ``` Serializer ---------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index eff2151e9856c..7e7f634ce00ec 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG --- * Remove the deprecated `hide_user_not_found` configuration option, use `expose_security_errors` instead + * Remove the deprecated `algorithm` and `key` options from the OIDC token handler configuration, use `algorithms` and `keyset` instead * Remove `LazyFirewallContext::__invoke()` * Make `ExpressionCacheWarmer` class `final` diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php index de53d5e89bc26..7d11ae070f4a4 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/AccessToken/OidcTokenHandlerFactory.php @@ -92,35 +92,8 @@ public function addConfiguration(NodeBuilder $node): void ->arrayNode($this->getKey()) ->fixXmlConfig($this->getKey()) ->validate() - ->ifTrue(static fn ($v) => !isset($v['algorithm']) && !isset($v['algorithms'])) - ->thenInvalid('You must set either "algorithm" or "algorithms".') - ->end() - ->validate() - ->ifTrue(static fn ($v) => !isset($v['discovery']) && !isset($v['key']) && !isset($v['keyset'])) - ->thenInvalid('You must set either "discovery" or "key" or "keyset".') - ->end() - ->beforeNormalization() - ->ifTrue(static fn ($v) => isset($v['algorithm']) && \is_string($v['algorithm'])) - ->then(static function ($v) { - if (isset($v['algorithms'])) { - throw new InvalidConfigurationException('You cannot use both "algorithm" and "algorithms" at the same time.'); - } - $v['algorithms'] = [$v['algorithm']]; - unset($v['algorithm']); - - return $v; - }) - ->end() - ->beforeNormalization() - ->ifTrue(static fn ($v) => isset($v['key']) && \is_string($v['key'])) - ->then(static function ($v) { - if (isset($v['keyset'])) { - throw new InvalidConfigurationException('You cannot use both "key" and "keyset" at the same time.'); - } - $v['keyset'] = \sprintf('{"keys":[%s]}', $v['key']); - - return $v; - }) + ->ifTrue(static fn ($v) => !isset($v['discovery']) && !isset($v['keyset'])) + ->thenInvalid('You must set either "discovery" or "keyset".') ->end() ->children() ->arrayNode('discovery') @@ -155,19 +128,11 @@ public function addConfiguration(NodeBuilder $node): void ->isRequired() ->scalarPrototype()->end() ->end() - ->arrayNode('algorithm') - ->info('Algorithm used to sign the token.') - ->setDeprecated('symfony/security-bundle', '7.1', 'The "%node%" option is deprecated and will be removed in 8.0. Use the "algorithms" option instead.') - ->end() ->arrayNode('algorithms') ->info('Algorithms used to sign the token.') ->isRequired() ->scalarPrototype()->end() ->end() - ->scalarNode('key') - ->info('JSON-encoded JWK used to sign the token (must contain a "kty" key).') - ->setDeprecated('symfony/security-bundle', '7.1', 'The "%node%" option is deprecated and will be removed in 8.0. Use the "keyset" option instead.') - ->end() ->scalarNode('keyset') ->info('JSON-encoded JWKSet used to sign the token (must contain a list of valid public keys).') ->end() diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AccessTokenFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AccessTokenFactoryTest.php index 88b782363dbf9..00420f00190dd 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AccessTokenFactoryTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/AccessTokenFactoryTest.php @@ -104,53 +104,9 @@ public function testInvalidOidcTokenHandlerConfigurationKeyMissing() $config = [ 'token_handler' => [ 'oidc' => [ - 'algorithm' => 'RS256', - 'issuers' => ['https://www.example.com'], - 'audience' => 'audience', - ], - ], - ]; - - $factory = new AccessTokenFactory($this->createTokenHandlerFactories()); - - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('You must set either "discovery" or "key" or "keyset".'); - - $this->processConfig($config, $factory); - } - - public function testInvalidOidcTokenHandlerConfigurationDuplicatedKeyParameters() - { - $config = [ - 'token_handler' => [ - 'oidc' => [ - 'algorithm' => 'RS256', - 'issuers' => ['https://www.example.com'], - 'audience' => 'audience', - 'key' => 'key', - 'keyset' => 'keyset', - ], - ], - ]; - - $factory = new AccessTokenFactory($this->createTokenHandlerFactories()); - - $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('You cannot use both "key" and "keyset" at the same time.'); - - $this->processConfig($config, $factory); - } - - public function testInvalidOidcTokenHandlerConfigurationDuplicatedAlgorithmParameters() - { - $config = [ - 'token_handler' => [ - 'oidc' => [ - 'algorithm' => 'RS256', 'algorithms' => ['RS256'], 'issuers' => ['https://www.example.com'], 'audience' => 'audience', - 'keyset' => 'keyset', ], ], ]; @@ -158,7 +114,7 @@ public function testInvalidOidcTokenHandlerConfigurationDuplicatedAlgorithmParam $factory = new AccessTokenFactory($this->createTokenHandlerFactories()); $this->expectException(InvalidConfigurationException::class); - $this->expectExceptionMessage('You cannot use both "algorithm" and "algorithms" at the same time.'); + $this->expectExceptionMessage('You must set either "discovery" or "keyset".'); $this->processConfig($config, $factory); } @@ -183,46 +139,6 @@ public function testInvalidOidcTokenHandlerConfigurationMissingAlgorithmParamete $this->processConfig($config, $factory); } - /** - * @group legacy - * - * @expectedDeprecation Since symfony/security-bundle 7.1: The "key" option is deprecated and will be removed in 8.0. Use the "keyset" option instead. - */ - public function testOidcTokenHandlerConfigurationWithSingleAlgorithm() - { - $container = new ContainerBuilder(); - $jwk = '{"kty":"EC","crv":"P-256","x":"0QEAsI1wGI-dmYatdUZoWSRWggLEpyzopuhwk-YUnA4","y":"KYl-qyZ26HobuYwlQh-r0iHX61thfP82qqEku7i0woo","d":"iA_TV2zvftni_9aFAQwFO_9aypfJFCSpcCyevDvz220"}'; - $config = [ - 'token_handler' => [ - 'oidc' => [ - 'algorithm' => 'RS256', - 'issuers' => ['https://www.example.com'], - 'audience' => 'audience', - 'key' => $jwk, - ], - ], - ]; - - $factory = new AccessTokenFactory($this->createTokenHandlerFactories()); - $finalizedConfig = $this->processConfig($config, $factory); - - $factory->createAuthenticator($container, 'firewall1', $finalizedConfig, 'userprovider'); - - $this->assertTrue($container->hasDefinition('security.authenticator.access_token.firewall1')); - $this->assertTrue($container->hasDefinition('security.access_token_handler.firewall1')); - - $expected = [ - 'index_0' => (new ChildDefinition('security.access_token_handler.oidc.signature')) - ->replaceArgument(0, ['RS256']), - 'index_1' => (new ChildDefinition('security.access_token_handler.oidc.jwkset')) - ->replaceArgument(0, \sprintf('{"keys":[%s]}', $jwk)), - 'index_2' => 'audience', - 'index_3' => ['https://www.example.com'], - 'index_4' => 'sub', - ]; - $this->assertEquals($expected, $container->getDefinition('security.access_token_handler.firewall1')->getArguments()); - } - public function testOidcTokenHandlerConfigurationWithMultipleAlgorithms() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AccessToken/config_oidc_jwe.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AccessToken/config_oidc_jwe.yml index 7d17d073df9cc..9885b3d267e50 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AccessToken/config_oidc_jwe.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AccessToken/config_oidc_jwe.yml @@ -24,7 +24,7 @@ security: claim: 'username' audience: 'Symfony OIDC' issuers: [ 'https://www.example.com' ] - algorithm: 'ES256' + algorithms: ['ES256'] # tip: use https://mkjwk.org/ to generate a JWK keyset: '{"keys":[{"kty":"EC","d":"iA_TV2zvftni_9aFAQwFO_9aypfJFCSpcCyevDvz220","crv":"P-256","x":"0QEAsI1wGI-dmYatdUZoWSRWggLEpyzopuhwk-YUnA4","y":"KYl-qyZ26HobuYwlQh-r0iHX61thfP82qqEku7i0woo"}]}' encryption: