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

Skip to content

Commit c522cc9

Browse files
committed
bug #42321 [PasswordHasher] Fix usage of PasswordHasherAdapter in PasswordHasherFactory (peter17)
This PR was squashed before being merged into the 5.3 branch. Discussion ---------- [PasswordHasher] Fix usage of PasswordHasherAdapter in PasswordHasherFactory | Q | A | ------------- | --- | Branch? | 5.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix explained below | License | MIT Using migrate_from with a PasswordEncoderInterface was working fine in Symfony 5.2. It Symfony 5.3, it resulted in an error, because getHasherConfigFromAlgorithm would access it before it is decorated with the adapter. Full stack-trace: ``` TypeError: Argument 1 passed to Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory::createHasher() must be of the type array, object given, called in /var/www/html/vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php on line 157 at vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php:73 at Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory->createHasher(object(LegacyPasswordEncoder), true) (vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php:157) at Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory->getHasherConfigFromAlgorithm(array('algorithm' => 'native', 'cost' => 15, 'hash_algorithm' => 'sha512', 'key_length' => 40, 'ignore_case' => false, 'encode_as_base64' => true, 'iterations' => 5000, 'memory_cost' => null, 'time_cost' => null)) (vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php:77) at Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory->createHasher(array('algorithm' => 'native', 'cost' => 15, 'migrate_from' => array('legacy'), 'hash_algorithm' => 'sha512', 'key_length' => 40, 'ignore_case' => false, 'encode_as_base64' => true, 'iterations' => 5000, 'memory_cost' => null, 'time_cost' => null), true) (vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php:137) at Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory->getHasherConfigFromAlgorithm(array('algorithm' => 'native', 'cost' => 15, 'migrate_from' => array('legacy'), 'hash_algorithm' => 'sha512', 'key_length' => 40, 'ignore_case' => false, 'encode_as_base64' => true, 'iterations' => 5000, 'memory_cost' => null, 'time_cost' => null)) (vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php:77) at Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory->createHasher(array('algorithm' => 'auto', 'cost' => 15, 'migrate_from' => array('legacy'), 'hash_algorithm' => 'sha512', 'key_length' => 40, 'ignore_case' => false, 'encode_as_base64' => true, 'iterations' => 5000, 'memory_cost' => null, 'time_cost' => null)) (vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php:113) at Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory->createHasherUsingAdapter('App\\Entity\\User') (vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php:65) at Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory->getPasswordHasher(object(User)) (vendor/symfony/security-core/Authentication/Provider/DaoAuthenticationProvider.php:100) at Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider->checkAuthentication(object(User), object(UsernamePasswordToken)) (vendor/symfony/security-core/Authentication/Provider/UserAuthenticationProvider.php:86) at Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider->authenticate(object(UsernamePasswordToken)) (vendor/symfony/security-core/Authentication/AuthenticationProviderManager.php:88) at Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager->authenticate(object(UsernamePasswordToken)) (vendor/symfony/security-http/Firewall/UsernamePasswordFormAuthenticationListener.php:108) at Symfony\Component\Security\Http\Firewall\UsernamePasswordFormAuthenticationListener->attemptAuthentication(object(Request)) (vendor/symfony/security-http/Firewall/AbstractAuthenticationListener.php:136) at Symfony\Component\Security\Http\Firewall\AbstractAuthenticationListener->authenticate(object(RequestEvent)) (vendor/symfony/security-bundle/Debug/WrappedLazyListener.php:49) at Symfony\Bundle\SecurityBundle\Debug\WrappedLazyListener->authenticate(object(RequestEvent)) (vendor/symfony/security-http/Firewall/AbstractListener.php:26) at Symfony\Component\Security\Http\Firewall\AbstractListener->__invoke(object(RequestEvent)) (vendor/symfony/security-bundle/Debug/TraceableFirewallListener.php:62) at Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener->callListeners(object(RequestEvent), object(Generator)) (vendor/symfony/security-http/Firewall.php:86) at Symfony\Component\Security\Http\Firewall->onKernelRequest(object(RequestEvent), 'kernel.request', object(TraceableEventDispatcher)) (vendor/symfony/event-dispatcher/Debug/WrappedListener.php:117) at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(RequestEvent), 'kernel.request', object(TraceableEventDispatcher)) (vendor/symfony/event-dispatcher/EventDispatcher.php:230) at Symfony\Component\EventDispatcher\EventDispatcher->callListeners(array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.request', object(RequestEvent)) (vendor/symfony/event-dispatcher/EventDispatcher.php:59) at Symfony\Component\EventDispatcher\EventDispatcher->dispatch(object(RequestEvent), 'kernel.request') (vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php:151) at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch(object(RequestEvent), 'kernel.request') (vendor/symfony/http-kernel/HttpKernel.php:133) at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1) (vendor/symfony/http-kernel/HttpKernel.php:79) at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true) (vendor/symfony/http-kernel/Kernel.php:199) at Symfony\Component\HttpKernel\Kernel->handle(object(Request)) (public/index.php:20) ``` My confguration in security.yml: ``` encoders: legacy: id: 'App\Utils\LegacyPasswordEncoder' App\Entity\User: algorithm: auto cost: 15 migrate_from: - legacy ``` Commits ------- c7442cb [PasswordHasher] Fix usage of PasswordHasherAdapter in PasswordHasherFactory
2 parents 8df7732 + c7442cb commit c522cc9

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,7 @@ public function getPasswordHasher($user): PasswordHasherInterface
6161
throw new \RuntimeException(sprintf('No password hasher has been configured for account "%s".', \is_object($user) ? get_debug_type($user) : $user));
6262
}
6363

64-
if (!$this->passwordHashers[$hasherKey] instanceof PasswordHasherInterface) {
65-
$this->passwordHashers[$hasherKey] = $this->passwordHashers[$hasherKey] instanceof PasswordEncoderInterface
66-
? new PasswordHasherAdapter($this->passwordHashers[$hasherKey])
67-
: $this->createHasher($this->passwordHashers[$hasherKey])
68-
;
69-
}
70-
71-
return $this->passwordHashers[$hasherKey];
64+
return $this->createHasherUsingAdapter($hasherKey);
7265
}
7366

7467
/**
@@ -111,6 +104,18 @@ private function createHasher(array $config, bool $isExtra = false): PasswordHas
111104
return new MigratingPasswordHasher($hasher, ...$extrapasswordHashers);
112105
}
113106

107+
private function createHasherUsingAdapter(string $hasherKey): PasswordHasherInterface
108+
{
109+
if (!$this->passwordHashers[$hasherKey] instanceof PasswordHasherInterface) {
110+
$this->passwordHashers[$hasherKey] = $this->passwordHashers[$hasherKey] instanceof PasswordEncoderInterface
111+
? new PasswordHasherAdapter($this->passwordHashers[$hasherKey])
112+
: $this->createHasher($this->passwordHashers[$hasherKey])
113+
;
114+
}
115+
116+
return $this->passwordHashers[$hasherKey];
117+
}
118+
114119
private function getHasherConfigFromAlgorithm(array $config): array
115120
{
116121
if ('auto' === $config['algorithm']) {
@@ -142,8 +147,8 @@ private function getHasherConfigFromAlgorithm(array $config): array
142147
$hasherChain = [$this->createHasher($config, true)];
143148

144149
foreach ($frompasswordHashers as $name) {
145-
if ($hasher = $this->passwordHashers[$name] ?? false) {
146-
$hasher = $hasher instanceof PasswordHasherInterface ? $hasher : $this->createHasher($hasher, true);
150+
if (isset($this->passwordHashers[$name])) {
151+
$hasher = $this->createHasherUsingAdapter($name);
147152
} else {
148153
$hasher = $this->createHasher(['algorithm' => $name], true);
149154
}

src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,29 @@ public function testMigrateFrom()
163163
$this->assertStringStartsWith(\SODIUM_CRYPTO_PWHASH_STRPREFIX, $hasher->hash('foo', null));
164164
}
165165

166+
/**
167+
* @group legacy
168+
*/
169+
public function testMigrateFromLegacy()
170+
{
171+
if (!SodiumPasswordHasher::isSupported()) {
172+
$this->markTestSkipped('Sodium is not available');
173+
}
174+
175+
$factory = new PasswordHasherFactory([
176+
'plaintext_encoder' => $plaintext = new PlaintextPasswordEncoder(),
177+
SomeUser::class => ['algorithm' => 'sodium', 'migrate_from' => ['bcrypt', 'plaintext_encoder']],
178+
]);
179+
180+
$hasher = $factory->getPasswordHasher(SomeUser::class);
181+
$this->assertInstanceOf(MigratingPasswordHasher::class, $hasher);
182+
183+
$this->assertTrue($hasher->verify((new SodiumPasswordHasher())->hash('foo', null), 'foo', null));
184+
$this->assertTrue($hasher->verify((new NativePasswordHasher(null, null, null, \PASSWORD_BCRYPT))->hash('foo', null), 'foo', null));
185+
$this->assertTrue($hasher->verify($plaintext->encodePassword('foo', null), 'foo', null));
186+
$this->assertStringStartsWith(\SODIUM_CRYPTO_PWHASH_STRPREFIX, $hasher->hash('foo', null));
187+
}
188+
166189
public function testDefaultMigratingHashers()
167190
{
168191
$this->assertInstanceOf(

0 commit comments

Comments
 (0)