Skip to content

Commit 0427282

Browse files
[Security] Support hashing the hashed password using crc32c when putting the user in the session
1 parent 251a508 commit 0427282

File tree

4 files changed

+31
-8
lines changed

4 files changed

+31
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Add encryption support to `OidcTokenHandler` (JWE)
88
* Replace `$hideAccountStatusExceptions` argument with `$exposeSecurityErrors` in `AuthenticatorManager` constructor
99
* Add argument `$identifierNormalizer` to `UserBadge::__construct()` to allow normalizing the identifier
10+
* Support hashing the hashed password using crc32c when putting the user in the session
1011

1112
7.2
1213
---

Firewall/ContextListener.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,16 @@ private static function hasUserChanged(UserInterface $originalUser, TokenInterfa
292292
}
293293

294294
if ($originalUser instanceof PasswordAuthenticatedUserInterface || $refreshedUser instanceof PasswordAuthenticatedUserInterface) {
295-
if (!$originalUser instanceof PasswordAuthenticatedUserInterface
296-
|| !$refreshedUser instanceof PasswordAuthenticatedUserInterface
297-
|| $refreshedUser->getPassword() !== ($originalUser->getPassword() ?? $refreshedUser->getPassword())
295+
if (!$originalUser instanceof PasswordAuthenticatedUserInterface || !$refreshedUser instanceof PasswordAuthenticatedUserInterface) {
296+
return true;
297+
}
298+
299+
$originalPassword = $originalUser->getPassword();
300+
$refreshedPassword = $refreshedUser->getPassword();
301+
302+
if (null !== $originalPassword
303+
&& $refreshedPassword !== $originalPassword
304+
&& (8 !== \strlen($originalPassword) || hash('crc32c', $refreshedPassword ?? $originalPassword) !== $originalPassword)
298305
) {
299306
return true;
300307
}
@@ -303,7 +310,7 @@ private static function hasUserChanged(UserInterface $originalUser, TokenInterfa
303310
return true;
304311
}
305312

306-
if ($originalUser instanceof LegacyPasswordAuthenticatedUserInterface && $refreshedUser instanceof LegacyPasswordAuthenticatedUserInterface && $originalUser->getSalt() !== $refreshedUser->getSalt()) {
313+
if ($originalUser instanceof LegacyPasswordAuthenticatedUserInterface && $originalUser->getSalt() !== $refreshedUser->getSalt()) {
307314
return true;
308315
}
309316
}

Tests/Firewall/ContextListenerTest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,14 @@ public function testOnKernelResponseRemoveListener()
377377
$this->assertEmpty($dispatcher->getListeners());
378378
}
379379

380-
public function testRemovingPasswordFromSessionDoesntInvalidateTheToken()
380+
/**
381+
* @testWith [true]
382+
* [false]
383+
* [null]
384+
*/
385+
public function testNullOrHashedPasswordInSessionDoesntInvalidateTheToken(?bool $hashPassword)
381386
{
382-
$user = new CustomUser('user', ['ROLE_USER'], 'pass');
387+
$user = new CustomUser('user', ['ROLE_USER'], 'pass', $hashPassword);
383388

384389
$userProvider = $this->createMock(UserProviderInterface::class);
385390
$userProvider->expects($this->once())

Tests/Fixtures/CustomUser.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ final class CustomUser implements UserInterface, PasswordAuthenticatedUserInterf
1919
public function __construct(
2020
private string $username,
2121
private array $roles,
22-
private ?string $password = null,
22+
private ?string $password,
23+
private ?bool $hashPassword,
2324
) {
2425
}
2526

@@ -44,6 +45,15 @@ public function eraseCredentials(): void
4445

4546
public function __serialize(): array
4647
{
47-
return [\sprintf("\0%s\0username", self::class) => $this->username];
48+
$data = (array) $this;
49+
$passwordKey = \sprintf("\0%s\0password", self::class);
50+
51+
if ($this->hashPassword) {
52+
$data[$passwordKey] = hash('crc32c', $this->password);
53+
} elseif (null !== $this->hashPassword) {
54+
unset($data[$passwordKey]);
55+
}
56+
57+
return $data;
4858
}
4959
}

0 commit comments

Comments
 (0)