diff --git a/UPGRADE-4.3.md b/UPGRADE-4.3.md index c52cb7436c351..3f5f22164dfaa 100644 --- a/UPGRADE-4.3.md +++ b/UPGRADE-4.3.md @@ -168,13 +168,14 @@ Security ``` * The `Argon2iPasswordEncoder` class has been deprecated, use `SodiumPasswordEncoder` instead. + * The `BCryptPasswordEncoder` class has been deprecated, use `NativePasswordEncoder` instead. * Not implementing the methods `__serialize` and `__unserialize` in classes implementing the `TokenInterface` is deprecated SecurityBundle -------------- - * Configuring encoders using `argon2i` as algorithm has been deprecated, use `auto` instead. + * Configuring encoders using `argon2i` or `bcrypt` as algorithm has been deprecated, use `auto` instead. TwigBridge ---------- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index 2036cabcd90fe..7c409d4630d2d 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -342,6 +342,7 @@ Security ``` * The `Argon2iPasswordEncoder` class has been removed, use `SodiumPasswordEncoder` instead. + * The `BCryptPasswordEncoder` class has been removed, use `NativePasswordEncoder` instead. * Classes implementing the `TokenInterface` must implement the two new methods `__serialize` and `__unserialize` @@ -364,7 +365,7 @@ SecurityBundle changed to underscores. Before: `my-cookie` deleted the `my_cookie` cookie (with an underscore). After: `my-cookie` deletes the `my-cookie` cookie (with a dash). - * Configuring encoders using `argon2i` as algorithm is not supported anymore, use `sodium` instead. + * Configuring encoders using `argon2i` or `bcrypt` as algorithm is not supported anymore, use `auto` instead. Serializer ---------- diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index 15f59f47540f2..84ad3e4c8b92e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -70,7 +70,7 @@ protected function configure() security: encoders: Symfony\Component\Security\Core\User\User: plaintext - App\Entity\User: bcrypt + App\Entity\User: auto If you execute the command non-interactively, the first available configured diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 0463e9011dd92..af4260f04c428 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -558,6 +558,8 @@ private function createEncoder($config, ContainerBuilder $container) // bcrypt encoder if ('bcrypt' === $config['algorithm']) { + @trigger_error('Configuring an encoder with "bcrypt" as algorithm is deprecated since Symfony 4.3, use "auto" instead.', E_USER_DEPRECATED); + return [ 'class' => 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder', 'arguments' => [$config['cost'] ?? 13], diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 1405ef4bd8fe1..ef318946ce66c 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -306,14 +306,10 @@ public function testEncoders() 'arguments' => ['sha1', false, 5, 30], ], 'JMS\FooBundle\Entity\User6' => [ - 'class' => 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder', - 'arguments' => [15], - ], - 'JMS\FooBundle\Entity\User7' => [ 'class' => 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder', 'arguments' => [8, 102400, 15], ], - 'JMS\FooBundle\Entity\User8' => [ + 'JMS\FooBundle\Entity\User7' => [ 'algorithm' => 'auto', 'hash_algorithm' => 'sha512', 'key_length' => 40, @@ -371,25 +367,13 @@ public function testEncodersWithLibsodium() 'arguments' => ['sha1', false, 5, 30], ], 'JMS\FooBundle\Entity\User6' => [ - 'class' => 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder', - 'arguments' => [15], + 'class' => 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder', + 'arguments' => [8, 102400, 15], ], 'JMS\FooBundle\Entity\User7' => [ 'class' => 'Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder', 'arguments' => [8, 128 * 1024 * 1024], ], - 'JMS\FooBundle\Entity\User8' => [ - 'algorithm' => 'auto', - 'hash_algorithm' => 'sha512', - 'key_length' => 40, - 'ignore_case' => false, - 'encode_as_base64' => true, - 'iterations' => 5000, - 'cost' => null, - 'memory_cost' => null, - 'time_cost' => null, - 'threads' => null, - ], ]], $container->getDefinition('security.encoder_factory.generic')->getArguments()); } @@ -441,15 +425,42 @@ public function testEncodersWithArgon2i() 'arguments' => ['sha1', false, 5, 30], ], 'JMS\FooBundle\Entity\User6' => [ - 'class' => 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder', - 'arguments' => [15], + 'class' => 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder', + 'arguments' => [8, 102400, 15], ], 'JMS\FooBundle\Entity\User7' => [ 'class' => 'Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder', 'arguments' => [256, 1, 2], ], - 'JMS\FooBundle\Entity\User8' => [ - 'algorithm' => 'auto', + ]], $container->getDefinition('security.encoder_factory.generic')->getArguments()); + } + + /** + * @group legacy + */ + public function testEncodersWithBCrypt() + { + $container = $this->getContainer('bcrypt_encoder'); + + $this->assertEquals([[ + 'JMS\FooBundle\Entity\User1' => [ + 'class' => 'Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder', + 'arguments' => [false], + ], + 'JMS\FooBundle\Entity\User2' => [ + 'algorithm' => 'sha1', + 'encode_as_base64' => false, + 'iterations' => 5, + 'hash_algorithm' => 'sha512', + 'key_length' => 40, + 'ignore_case' => false, + 'cost' => null, + 'memory_cost' => null, + 'time_cost' => null, + 'threads' => null, + ], + 'JMS\FooBundle\Entity\User3' => [ + 'algorithm' => 'md5', 'hash_algorithm' => 'sha512', 'key_length' => 40, 'ignore_case' => false, @@ -460,6 +471,19 @@ public function testEncodersWithArgon2i() 'time_cost' => null, 'threads' => null, ], + 'JMS\FooBundle\Entity\User4' => new Reference('security.encoder.foo'), + 'JMS\FooBundle\Entity\User5' => [ + 'class' => 'Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder', + 'arguments' => ['sha1', false, 5, 30], + ], + 'JMS\FooBundle\Entity\User6' => [ + 'class' => 'Symfony\Component\Security\Core\Encoder\NativePasswordEncoder', + 'arguments' => [8, 102400, 15], + ], + 'JMS\FooBundle\Entity\User7' => [ + 'class' => 'Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder', + 'arguments' => [15], + ], ]], $container->getDefinition('security.encoder_factory.generic')->getArguments()); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/bcrypt_encoder.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/bcrypt_encoder.php new file mode 100644 index 0000000000000..1afad79e4fca3 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/bcrypt_encoder.php @@ -0,0 +1,12 @@ +load('container1.php', $container); + +$container->loadFromExtension('security', [ + 'encoders' => [ + 'JMS\FooBundle\Entity\User7' => [ + 'algorithm' => 'bcrypt', + 'cost' => 15, + ], + ], +]); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php index 06afe665d24ae..3c9e6104eecc3 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php @@ -22,16 +22,12 @@ 'key_length' => 30, ], 'JMS\FooBundle\Entity\User6' => [ - 'algorithm' => 'bcrypt', - 'cost' => 15, - ], - 'JMS\FooBundle\Entity\User7' => [ 'algorithm' => 'native', 'time_cost' => 8, 'memory_cost' => 100, 'cost' => 15, ], - 'JMS\FooBundle\Entity\User8' => [ + 'JMS\FooBundle\Entity\User7' => [ 'algorithm' => 'auto', ], ], diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/bcrypt_encoder.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/bcrypt_encoder.xml new file mode 100644 index 0000000000000..a98400c5f043a --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/bcrypt_encoder.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml index 9a3cae7159a2b..c919a7f276732 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -16,11 +16,9 @@ - + - - - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/bcrypt_encoder.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/bcrypt_encoder.yml new file mode 100644 index 0000000000000..3f1a526215204 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/bcrypt_encoder.yml @@ -0,0 +1,8 @@ +imports: + - { resource: container1.yml } + +security: + encoders: + JMS\FooBundle\Entity\User7: + algorithm: bcrypt + cost: 15 diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml index a51b0c49cafb3..03b9aaf6ef5b9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml @@ -16,14 +16,11 @@ security: iterations: 5 key_length: 30 JMS\FooBundle\Entity\User6: - algorithm: bcrypt - cost: 15 - JMS\FooBundle\Entity\User7: algorithm: native time_cost: 8 memory_cost: 100 cost: 15 - JMS\FooBundle\Entity\User8: + JMS\FooBundle\Entity\User7: algorithm: auto providers: diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php index 15cea530d50ef..7e90562246228 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php @@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder; use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; +use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder; use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder; use Symfony\Component\Security\Core\Encoder\SodiumPasswordEncoder; @@ -54,8 +55,12 @@ public function testEncodeNoPasswordNoInteraction() $this->assertEquals($statusCode, 1); } + /** + * @group legacy + */ public function testEncodePasswordBcrypt() { + $this->setupBcrypt(); $this->passwordEncoderCommandTester->execute([ 'command' => 'security:encode-password', 'password' => 'password', @@ -95,6 +100,23 @@ public function testEncodePasswordArgon2i() $this->assertTrue($encoder->isPasswordValid($hash, 'password', null)); } + public function testEncodePasswordNative() + { + $this->passwordEncoderCommandTester->execute([ + 'command' => 'security:encode-password', + 'password' => 'password', + 'user-class' => 'Custom\Class\Native\User', + ], ['interactive' => false]); + + $output = $this->passwordEncoderCommandTester->getDisplay(); + $this->assertContains('Password encoding succeeded', $output); + + $encoder = new NativePasswordEncoder(); + preg_match('# Encoded password\s{1,}([\w+\/$.,=]+={0,2})\s+#', $output, $matches); + $hash = $matches[1]; + $this->assertTrue($encoder->isPasswordValid($hash, 'password', null)); + } + public function testEncodePasswordSodium() { if (!SodiumPasswordEncoder::isSupported()) { @@ -162,12 +184,12 @@ public function testEncodePasswordEmptySaltOutput() $this->assertNotContains(' Generated salt ', $this->passwordEncoderCommandTester->getDisplay()); } - public function testEncodePasswordBcryptOutput() + public function testEncodePasswordNativeOutput() { $this->passwordEncoderCommandTester->execute([ 'command' => 'security:encode-password', 'password' => 'p@ssw0rd', - 'user-class' => 'Custom\Class\Bcrypt\User', + 'user-class' => 'Custom\Class\Native\User', ], ['interactive' => false]); $this->assertNotContains(' Generated salt ', $this->passwordEncoderCommandTester->getDisplay()); @@ -233,8 +255,8 @@ public function testEncodePasswordAsksNonProvidedUserClass() ], ['decorated' => false]); $this->assertContains(<<passwordEncoderCommandTester = new CommandTester($passwordEncoderCommand); } + private function setupBcrypt() + { + putenv('COLUMNS='.(119 + \strlen(PHP_EOL))); + $kernel = $this->createKernel(['test_case' => 'PasswordEncode', 'root_config' => 'bcrypt.yml']); + $kernel->boot(); + + $application = new Application($kernel); + + $passwordEncoderCommand = $application->get('security:encode-password'); + + $this->passwordEncoderCommandTester = new CommandTester($passwordEncoderCommand); + } + private function setupSodium() { putenv('COLUMNS='.(119 + \strlen(PHP_EOL))); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/bcrypt.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/bcrypt.yml new file mode 100644 index 0000000000000..1928c0400b722 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/bcrypt.yml @@ -0,0 +1,7 @@ +imports: + - { resource: config.yml } + +security: + encoders: + Custom\Class\Bcrypt\User: + algorithm: bcrypt diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/config.yml index 82416b095748e..9ae5433246561 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/config.yml @@ -4,8 +4,8 @@ imports: security: encoders: Symfony\Component\Security\Core\User\User: plaintext - Custom\Class\Bcrypt\User: - algorithm: bcrypt + Custom\Class\Native\User: + algorithm: native cost: 10 Custom\Class\Pbkdf2\User: algorithm: pbkdf2 diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 5dc78560733f7..f7b868fcbadea 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -21,7 +21,8 @@ CHANGELOG * Dispatch `AuthenticationFailureEvent` on `security.authentication.failure` * Dispatch `InteractiveLoginEvent` on `security.interactive_login` * Dispatch `SwitchUserEvent` on `security.switch_user` - * Deprecated `Argon2iPasswordEncoder`, use `SodiumPasswordEncoder` + * Deprecated `Argon2iPasswordEncoder`, use `SodiumPasswordEncoder` instead + * Deprecated `BCryptPasswordEncoder`, use `NativePasswordEncoder` instead 4.2.0 ----- diff --git a/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php index 7855552af61a1..d14949465c0ee 100644 --- a/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php +++ b/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php @@ -11,11 +11,15 @@ namespace Symfony\Component\Security\Core\Encoder; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', BCryptPasswordEncoder::class, NativePasswordEncoder::class), E_USER_DEPRECATED); + use Symfony\Component\Security\Core\Exception\BadCredentialsException; /** * @author Elnur Abdurrakhimov * @author Terje BrĂ¥ten + * + * @deprecated since Symfony 4.3, use NativePasswordEncoder instead */ class BCryptPasswordEncoder extends BasePasswordEncoder implements SelfSaltingEncoderInterface { diff --git a/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php b/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php index 7d87c6f904ef0..150190dc4c161 100644 --- a/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php +++ b/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php @@ -106,6 +106,7 @@ private function getEncoderConfigFromAlgorithm($config) ], ]; + /* @deprecated since Symfony 4.3 */ case 'bcrypt': return [ 'class' => BCryptPasswordEncoder::class, diff --git a/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php b/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php index 7f9dbe7f33fd8..4e8fcde7b0692 100644 --- a/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php @@ -16,6 +16,8 @@ /** * @author Elnur Abdurrakhimov + * + * @group legacy */ class BCryptPasswordEncoderTest extends TestCase { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy