Nicolas Grekas
Contributed by Nicolas Grekas in #31594 , #31597 and #31843

In Symfony 4.3 we introduced a native password encoder to hash your user passwords with the best possible algorithm available in your server:

1
2
3
4
5
6
7
# config/packages/security.yaml
security:
    # ...
    encoders:
        App\Entity\User:
            algorithm: auto
            cost: 14

This algorithm is selected automatically and can change over time, so different users will end up using different algorithms. Technically this is not a problem because Symfony knows how to hash and compare each password, so all users will be able to log in. However, it would be great if all users always used the best possible algorithm.

In Symfony 4.4, when a user successfully authenticates, Symfony checks if a better hashing algorithm is available and rehashes the password so you can store the updated hash. In practice, when using the entity user provider, you only need to update the Doctrine repository associated to users and implement the Symfony\Component\Security\Core\User\PasswordUpgraderInterface.

This interface defines a single method named upgradePassword() which Symfony will call when the user password must be rehashed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/Repository/UserRepository.php
namespace App\Repository;

// ...
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;

class UserRepository extends EntityRepository implements PasswordUpgraderInterface
{
    // ...

    public function upgradePassword(UserInterface $user, string $newEncodedPassword): void
    {
        // this code is only an example; the exact code will depend on
        // your own application needs
        $user->setPassword($newEncodedPassword);
        $this->getEntityManager()->flush($user);
    }
}

Read the docs about this new feature to learn how to implement it when using a custom user provider or a custom password encoder.

Published in #Living on the edge