Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Security] deprecate BCryptPasswordEncoder in favor of NativePasswordEncoder #31170

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

Merged
merged 1 commit into from
Apr 19, 2019
Merged
Show file tree
Hide file tree
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
3 changes: 2 additions & 1 deletion UPGRADE-4.3.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
----------
Expand Down
3 changes: 2 additions & 1 deletion UPGRADE-5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand All @@ -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
----------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected function configure()
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
App\Entity\User: bcrypt
App\Entity\User: auto
</comment>

If you execute the command non-interactively, the first available configured
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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());
}

Expand Down Expand Up @@ -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,
Expand All @@ -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());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

$this->load('container1.php', $container);

$container->loadFromExtension('security', [
'encoders' => [
'JMS\FooBundle\Entity\User7' => [
'algorithm' => 'bcrypt',
'cost' => 15,
],
],
]);
Original file line number Diff line number Diff line change
Expand Up @@ -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',
],
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://symfony.com/schema/dic/security"
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">

<imports>
<import resource="container1.xml"/>
</imports>

<sec:config>
<sec:encoder class="JMS\FooBundle\Entity\User7" algorithm="bcrypt" cost="15" />
</sec:config>

</container>
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@

<encoder class="JMS\FooBundle\Entity\User5" algorithm="pbkdf2" hash-algorithm="sha1" encode-as-base64="false" iterations="5" key-length="30" />

<encoder class="JMS\FooBundle\Entity\User6" algorithm="bcrypt" cost="15" />
<encoder class="JMS\FooBundle\Entity\User6" algorithm="native" time-cost="8" memory-cost="100" cost="15" />

<encoder class="JMS\FooBundle\Entity\User7" algorithm="native" time-cost="8" memory-cost="100" cost="15" />

<encoder class="JMS\FooBundle\Entity\User8" algorithm="auto" />
<encoder class="JMS\FooBundle\Entity\User7" algorithm="auto" />

<provider name="default">
<memory>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
imports:
- { resource: container1.yml }

security:
encoders:
JMS\FooBundle\Entity\User7:
algorithm: bcrypt
cost: 15
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -233,8 +255,8 @@ public function testEncodePasswordAsksNonProvidedUserClass()
], ['decorated' => false]);

$this->assertContains(<<<EOTXT
For which user class would you like to encode a password? [Custom\Class\Bcrypt\User]:
[0] Custom\Class\Bcrypt\User
For which user class would you like to encode a password? [Custom\Class\Native\User]:
[0] Custom\Class\Native\User
[1] Custom\Class\Pbkdf2\User
[2] Custom\Class\Test\User
[3] Symfony\Component\Security\Core\User\User
Expand Down Expand Up @@ -301,6 +323,19 @@ private function setupArgon2i()
$this->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)));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
imports:
- { resource: config.yml }

security:
encoders:
Custom\Class\Bcrypt\User:
algorithm: bcrypt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/Symfony/Component/Security/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
* @author Terje Bråten <[email protected]>
*
* @deprecated since Symfony 4.3, use NativePasswordEncoder instead
*/
class BCryptPasswordEncoder extends BasePasswordEncoder implements SelfSaltingEncoderInterface
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ private function getEncoderConfigFromAlgorithm($config)
],
];

/* @deprecated since Symfony 4.3 */
case 'bcrypt':
return [
'class' => BCryptPasswordEncoder::class,
Expand Down
Loading