In my Symfony 5.3 (and upwards) projects, to enable some data in my tables for raw development and for the testing, I use Hautelook/Alice Bundle.

One of the elements that I want to be able to fake are users. Unfortunately, I didn’t find any direct way using the bundle pre-existing features to load hashed passwords. Meaning, there is no faker function to hash any string based on the defined Symfony User Password hashing (cfr. Symfony Security Definition)

  1. I could indeed use plain passwords. I’m only in dev and test, but the issue is that during the testing, I’ll try to connect and I’ll fall against the Security wall where Symfony will try to hash my input password against the stored password and so will fail
  2. I could define it by hand in the fixtures.yaml file of Hautelook/Alice. It could work regarding the above issue, but I would have to look at it by hand (there is console command to do that…) and I do want to find a structural way to do it
  3. I could use the Custom Faker Providers functionality of Alice bundle. That’s what I’m describing below.

It’s quite easy actually, you only need to follow the following Custom Faker Provider page.

So, let’s create a HashPasswordProvider

<?php

namespace App\DataFixtures\Providers;

use App\Entity\User;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;

class HashPasswordProvider
{
    /**
     * @var UserPasswordHasherInterface
     */
    private $hasher;
    public function __construct(UserPasswordHasherInterface $hasher)
    {
        $this->hasher = $hasher;
    }

    public function hashPassword(string $plainPassword): string
    {
        return $this->hasher->hashPassword(new User(), $plainPassword);
    }

}

Let’s break down the different elements:

  1. to be able to hash a password, you need to known which hashing algorithm is defined for the application. Fortunately, the following interface : UserPasswordHasherInterface will provide you the access to that knowledge.
    So, let’s inject it into our Class to benefit from it
    /**
     * @var UserPasswordHasherInterface
     */
    private $hasher;
    public function __construct(UserPasswordHasherInterface $hasher)
    {
        $this->hasher = $hasher;
    }

2. then, simply define a public function that will take the necessary input (here a plain password) and returns the hashed password using the UserPasswordEncoder injected

public function hashPassword(string $plainPassword): string
    {
        return $this->hasher->hashPassword(new User(), $plainPassword);
    }

3. after that, you need to define your new Custom Provider as a service tagging him for the Hautelook/Alice bundle to recognize it as a Custom data Provider

# config/services.yaml

services:
    App\DataFixtures\Providers\HashPasswordProvider:
        tags: [ { name: nelmio_alice.faker.provider } ]

4. finally, you are able to use that function into your fixtures file.

//fixtures\User.yaml
App\Entity\User:
    user_{1..10}:
        email: <email()>
        password: <hashPassword('plainPassword')>

It’s as simple as that.

Categories:

Tags:

2 Responses

  1. Hi,
    Thank you for your article, it saved me lot of time. Just 2 typos in 1st script:

    private $encoder; => private $hasher;

    and

    return $this->hasher->hasPassword(new User(), $plainPassword);

    => return $this->hasher->hashPassword(new User(), $plainPassword);

    best

Répondre à Obiwan Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *