English spoken conference

Symfony 5: The Fast Track

A new book to learn about developing modern Symfony 5 applications.

Support this project

New in Symfony 4.4: Password Migrations

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.

Comments

This is great! In a previous project I have implemented a similar feature using an event listener that hooks into the INTERACTIVE_LOGIN event an updates the reencoded password.
Wonderful. Is there a recipe for using this when migration FOSUserBundle (which has salt and password as two separate keys)?
Really nice ! This will be usefull

----

Small error on the "PasswordUpgraderInterface" URL, which points to Symfony 4.2 version instead of 4.4.
So great! So useful! Thanks!
@Antoine thanks for your comment! We've removed the URL and displayed the full FQCN of the interface instead.
Maybe it is not important it the current context but I thought that smf repositories are used only for read-only communication with DB. Am I wrong?
@Ilyas G, my thoughts exactly. Not sure it's the place where you expect it to be handled either. I much prefer an event or even user checker over this to be fair. We're free to do as we please though!
Lol, a custom user provider (as in the docs) is even a better place probably.

Really glad this feature came through though!
Login with SymfonyConnect to post a comment