Skip to content

Commit d95bd92

Browse files
authored
Merge pull request FriendsOfSymfony#2313 from stof/regenerate_hash
Regenerate the hash on password update
2 parents 81f872e + a9a08c2 commit d95bd92

File tree

6 files changed

+52
-3
lines changed

6 files changed

+52
-3
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Changelog
2525
* [BC break] The signature of the `UserManager` constructor has changed.
2626
* [BC break] The translation key `resetting.request.invalid_username` has been removed.
2727
* [BC break] The propel dependency was dropped.
28+
* [BC break] The `salt` field of the `User` class is now nullable.
2829

2930
### 2.0.0-alpha3 (2015-09-15)
3031

Model/User.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ abstract class User implements UserInterface, GroupableInterface
105105
*/
106106
public function __construct()
107107
{
108-
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
109108
$this->enabled = false;
110109
$this->roles = array();
111110
}
@@ -358,6 +357,14 @@ public function setUsernameCanonical($usernameCanonical)
358357
return $this;
359358
}
360359

360+
/**
361+
* {@inheritdoc}
362+
*/
363+
public function setSalt($salt)
364+
{
365+
$this->salt = $salt;
366+
}
367+
361368
public function setEmail($email)
362369
{
363370
$this->email = $email;

Model/UserInterface.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ public function getUsernameCanonical();
5555
*/
5656
public function setUsernameCanonical($usernameCanonical);
5757

58+
/**
59+
* @param string|null $salt
60+
*/
61+
public function setSalt($salt);
62+
5863
/**
5964
* Gets email.
6065
*

Resources/config/doctrine-mapping/User.orm.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
<field name="enabled" column="enabled" type="boolean" />
1818

19-
<field name="salt" column="salt" type="string" />
19+
<field name="salt" column="salt" type="string" nullable="true" />
2020

2121
<field name="password" column="password" type="string" />
2222

Tests/Util/PasswordUpdaterTest.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,42 @@ public function testUpdatePassword()
3737

3838
$this->encoderFactory->expects($this->once())
3939
->method('getEncoder')
40+
->with($user)
4041
->will($this->returnValue($encoder));
4142

4243
$encoder->expects($this->once())
4344
->method('encodePassword')
44-
->with('password', $user->getSalt())
45+
->with('password', $this->isType('string'))
4546
->will($this->returnValue('encodedPassword'));
4647

4748
$this->updater->hashPassword($user);
4849
$this->assertSame('encodedPassword', $user->getPassword(), '->updatePassword() sets encoded password');
50+
$this->assertNotNull($user->getSalt());
51+
$this->assertNull($user->getPlainPassword(), '->updatePassword() erases credentials');
52+
}
53+
54+
public function testUpdatePasswordWithBCrypt()
55+
{
56+
$encoder = $this->getMockBuilder('Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder')
57+
->disableOriginalConstructor()
58+
->getMock();
59+
$user = new TestUser();
60+
$user->setPlainPassword('password');
61+
$user->setSalt('old_salt');
62+
63+
$this->encoderFactory->expects($this->once())
64+
->method('getEncoder')
65+
->with($user)
66+
->will($this->returnValue($encoder));
67+
68+
$encoder->expects($this->once())
69+
->method('encodePassword')
70+
->with('password', $this->isNull())
71+
->will($this->returnValue('encodedPassword'));
72+
73+
$this->updater->hashPassword($user);
74+
$this->assertSame('encodedPassword', $user->getPassword(), '->updatePassword() sets encoded password');
75+
$this->assertNull($user->getSalt());
4976
$this->assertNull($user->getPlainPassword(), '->updatePassword() erases credentials');
5077
}
5178

Util/PasswordUpdater.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace FOS\UserBundle\Util;
1313

1414
use FOS\UserBundle\Model\UserInterface;
15+
use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder;
1516
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
1617

1718
/**
@@ -37,6 +38,14 @@ public function hashPassword(UserInterface $user)
3738
}
3839

3940
$encoder = $this->encoderFactory->getEncoder($user);
41+
42+
if ($encoder instanceof BCryptPasswordEncoder) {
43+
$user->setSalt(null);
44+
} else {
45+
$salt = rtrim(str_replace('+', '.', base64_encode(random_bytes(32))), '=');
46+
$user->setSalt($salt);
47+
}
48+
4049
$hashedPassword = $encoder->encodePassword($plainPassword, $user->getSalt());
4150
$user->setPassword($hashedPassword);
4251
$user->eraseCredentials();

0 commit comments

Comments
 (0)