Description
Symfony version(s) affected: 5.3.6
Description
I upgraded my app from Symfony 5.2 to 5.3. I am not able to log in to my app. These is an error:
Uncaught PHP Exception TypeError: "Argument 1 passed to Symfony\Component\PasswordHasher\Hasher\PasswordHasherFactory::createHasher() must be of the type array, object given, called in [...]/vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php on line 146" at [...]/vendor/symfony/password-hasher/Hasher/PasswordHasherFactory.php line 79
How to reproduce
My app is open source: https://github.com/TomaszGasior/RadioLista-v3
On v3.32
tag (with Symfony 5.2) I am able to log in without issues. On v3.33
tag (Sf 5.3) it's impossible to log in to my app.
Please note my app has dev-env specific security encoders settings so you may have remove config/dev/security.yaml
or set APP_ENV=prod
to really reproduce the issue.
Possible Solution
I found that the issue is caused by BC layer of new password hasher component. My app has it's own password encoder (for legacy sha1 passwords) which is improperly handled by BC layer when it's set as migrate_from
option.
Part of security.yaml:
encoders:
App\Entity\User:
algorithm: auto
cost: 12
migrate_from: [rl_v1, bcrypt] # removing this line "hides" the issue
rl_v1:
id: App\Security\Encoder\RLv1Encoder
I am able to fix the issue by modifying PasswordHasherFactory.php
from this
foreach ($frompasswordHashers as $name) {
if ($hasher = $this->passwordHashers[$name] ?? false) {
$hasher = $hasher instanceof PasswordHasherInterface ? $hasher : $this->createHasher($hasher, true);
} else {
$hasher = $this->createHasher(['algorithm' => $name], true);
}
$hasherChain[] = $hasher;
}
to this:
foreach ($frompasswordHashers as $name) {
if ($hasher = $this->passwordHashers[$name] ?? false) {
if (!$hasher instanceof PasswordHasherInterface && $hasher instanceof PasswordEncoderInterface) {
$hasher = new PasswordHasherAdapter($hasher);
}
else {
$hasher = $hasher instanceof PasswordHasherInterface ? $hasher : $this->createHasher($hasher, true);
}
} else {
$hasher = $this->createHasher(['algorithm' => $name], true);
}
$hasherChain[] = $hasher;
}
Please let me know it makes sense or not, I can create PR. :)