4

I am using EasyAdmin to add/edit users and wanted to ask if there is a possibility of encrypting your passwords? Password encryption worked previously when I used the Symfony 4 make:registration-form but I can't use that now, I have to use EasyAdmin.

easy_admin.yaml

easy_admin:
  entities:
    User:
     class: App\Entity\User
     password_encoding: { algorithm: 'bcrypt', cost: 12 }

(Actual) I go to EasyAdmin page (/admin), click User, Add User, fill in email (test@gmail.com) and password (test), click Save Changes.

Now the user is stored in the database but with plaintext password. enter image description here

(Expected) All of the above but password is encrypted.

D. Gillard
  • 63
  • 1
  • 1
  • 5
  • It has nothing to do with Easy Admin. You have to configure the security by yourself inside `packages/security.yaml` – Mike Doe Feb 18 '19 at 10:14
  • I wrote this in the security.yaml security: encoders: App\Entity\User: algorithm: argon2i – D. Gillard Feb 18 '19 at 10:19
  • Could you expand your question? Do you mean when you create/edit users through EasyAdmin it does not encrypt the passwords? – dbrumann Feb 18 '19 at 10:55
  • Yes that's what I mean – D. Gillard Feb 18 '19 at 10:57
  • Please add more details. Are you using any bundle for user management, e.g. FOSUserBundle? What does your configuration for EasyAdmin look like? – dbrumann Feb 18 '19 at 11:02
  • There is a short section in the docs on managing properties with EasyAdmin. Have you already tried this? https://symfony.com/doc/current/bundles/EasyAdminBundle/tutorials/custom-property-options.html#custom-entity-options – dbrumann Feb 18 '19 at 11:03
  • I saw it but I don't really understand how to use it. So I have to put password_encoding: ... in easy_admin.yaml but what then? – D. Gillard Feb 18 '19 at 11:17
  • As far as I can tell, this should solve your problem. The password should be encoded when saving it. Let's go step by step. Please add your `easy_admin.yaml` to the question. Then walk us through the process, e.g. go to user list, click create user, put in data X and then finish with expected result (user is created and the encrypted password is stored in the db) vs. actual result (e.g. the password in the database was saved as plaintext). If you can provide code changes you made that would help too. From there we can suggest changes and you can tell how they affect the actual result. – dbrumann Feb 18 '19 at 11:37
  • I added it to description – D. Gillard Feb 18 '19 at 11:59
  • 1
    Maybe here you find answer: https://github.com/EasyCorp/EasyAdminBundle/issues/1261. You should override UserController and manualy add password encoding/decoding. – Krzysztof Raciniewski Feb 18 '19 at 12:03

3 Answers3

6

New version compatible with Symfony 5:

<?php

namespace App\Controller;

use App\Entity\User;
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;

class AdminController extends EasyAdminController
{
    protected function persistUserEntity($user)
    {
        $encodedPassword = $this->encodePassword($user, $user->getPlainPassword());
        $user->setPassword($encodedPassword);

        parent::persistEntity($user);
    }

    protected function updateUserEntity($user)
    {
        $encodedPassword = $this->encodePassword($user, $user->getPlainPassword());
        $user->setPassword($encodedPassword);

        parent::updateEntity($user);
    }

    private function encodePassword($user, $password)
    {
        $passwordEncoderFactory = new EncoderFactory([
            User::class => new MessageDigestPasswordEncoder('sha512', true, 5000)
        ]);

        $encoder = $passwordEncoderFactory->getEncoder($user);

        return $encoder->encodePassword($password, $user->getSalt());
    }
}
raphox
  • 119
  • 1
  • 4
6

Code from my working project based on Symfony 5 and PHP 7.4

  1. Extend EasyAdminController:
<?php

declare(strict_types=1);

namespace App\Controller;

use App\Entity\User;
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

/**
 * Class AdminController.
 *
 * @author Dmitriy Atamaniuc <d.atamaniuc@gmail.com>
 */
final class AdminController extends EasyAdminController
{
    private UserPasswordEncoderInterface $encoder;

    private function setUserPlainPassword(User $user): void
    {
        if ($user->getPlainPassword()) {
            $user->setPassword($this->encoder->encodePassword($user, $user->getPlainPassword()));
        }
    }

    /**
     * @required
     */
    public function setEncoder(UserPasswordEncoderInterface $encoder): void
    {
        $this->encoder = $encoder;
    }

    public function persistUserEntity(User $user): void
    {
        $this->setUserPlainPassword($user);

        $this->persistEntity($user);
    }

    public function updateUserEntity(User $user): void
    {
        $this->setUserPlainPassword($user);

        $this->updateEntity($user);
    }
}
  1. Register your controller in EasyAdminBundle, edit config/routes/easy_admin.yaml:
easy_admin_bundle:
    resource: 'App\Controller\AdminController'
    prefix: /admin
    type: annotation
  1. Add plainPassword "virtual" property to your User entity:
/**
* @Assert\NotBlank()
* @Assert\Length(min=5, max=128)
*/
private ?string $plainPassword = null;

public function getPlainPassword(): ?string
{
    return $this->plainPassword;
}

public function setPlainPassword(string $password): void
{
    $this->plainPassword = $password;
}
  1. Update easy_admin.yaml
easy_admin:
    entities:
        User:
            class: App\Entity\User
            label: label.user
            new:
                title:  field.user.add_new
                fields:
                    # some fields like username here
                    - { property: username, label: field.user.username }
                    - { property: fullname, label: field.user.fullname, type: 'text' }
                    # plain password 
                    - { property: plainPassword, label: field.user.password, type: 'password' }
4

Extend EasyAdmin controller and handle User entity. Something like this:

namespace AppBundle\Controller\Admin;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
use AppBundle\Entity\User;

class AdminController extends BaseAdminController
{
    protected function prePersistUserEntity(User $user)
    {
        $encodedPassword = $this->encodePassword($user, $user->getPassword());
        $user->setPassword($encodedPassword);
    }

    protected function preUpdateUserEntity(User $user)
    {
        if (!$user->getPlainPassword()) {
            return;
        }
        $encodedPassword = $this->encodePassword($user, $user->getPlainPassword());
        $user->setPassword($encodedPassword);
    }

    private function encodePassword($user, $password)
    {
        $passwordEncoderFactory = $this->get('security.encoder_factory');
        $encoder = $passwordEncoderFactory->getEncoder($user);
        return $encoder->encodePassword($password, $user->getSalt());
    }

}

and_rest
  • 314
  • 2
  • 7