goodhand
goodhand

Reputation: 199

How to encode a password in Symfony 5?

I am trying to encode a password in Symfony and after carefully following the documentation here it still seems like I am doing something wrong.

This is my RegisterController.php:

<?php
    namespace App\Controller;

    use App\Entity\User;
    use App\Form\Type\UserType;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class RegisterController extends AbstractController
{
private $passwordEncoder;

public function __construct(UserPasswordEncoderInterface $passwordEncoder)
{
    $this->passwordEncoder = $passwordEncoder;        
}

/**
    * @Route("/register", name="user.register")
    */
public function create(Request $request)
{
    $user = new User();

    $form = $this->createForm(UserType::class, $user);

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $user->setPassword( 
            $this->passwordEncoder->encodePassword( $user, $user->getPassword() )
        );

The above returns the following error:

Neither the property "plainPassword" nor one of the methods "getPlainPassword()", "plainPassword()", "isPlainPassword()", "hasPlainPassword()", "__get()" exist and have public access in class "App\Entity\User".

And here is my Register.twig.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Register{% endblock %}</title>
        {# {% block stylesheets %}{% endblock %} #}
    </head>
    <body>
        <div class="container">
            <h2 class="form-signin-heading">Welcome, please register below</h2>
            {{ form(form) }}
        </div>

    </body>
</html>

And finally I have this setup in my security.yaml file:

security:    
   encoders:
        App\Entity\User:
            algorithm: auto

I guess it's something simple that I'm overlooking but I couldn't get it to work. It is my first time with Symfony.

Upvotes: 6

Views: 25641

Answers (6)

Sebastian Skurn&#243;g
Sebastian Skurn&#243;g

Reputation: 161

If you need to manually encode password, use cli command:

/bin/console security:encode-password

For symfony >= 6.0

/bin/console security:hash-password

Upvotes: 0

Gregory Neely
Gregory Neely

Reputation: 111

As of Symfony 5.3 UserPasswordEncoderInterface has been deprecated in favor of UserPasswordHasherInterface. See this article for more information. Symfony 6 fixtures UserPasswordHasherInterface

Upvotes: 1

Arnold Richmon
Arnold Richmon

Reputation: 331

Actually this happen because symfony detect if there is no "plainPassword" property in User entity. The purpose of using this "plainPassword" property is to be a temporary data, so we can encode it. What you need to do is set the "plainPassword" property mapped to be false in you form type.

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('plainPassword', RepeatedType::class, array(
            'type'              => PasswordType::class,
            'mapped'            => false,
            'first_options'     => array('label' => 'New password'),
            'second_options'    => array('label' => 'Confirm new password'),
            'invalid_message' => 'The password fields must match.',
        ))
    ;
}

And in your controller encode the "plainPassword" to be encoded "password":

/**
 * @Route("/register", name="app_register")
 */
public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder): Response
{
    $user = new User();
    $form = $this->createForm(RegistrationFormType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        // encode the plain password
        $user->setPassword(
            $passwordEncoder->encodePassword(
                $user,
                $form->get('plainPassword')->getData()
            )
        );

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($user);
        $entityManager->flush();

        // do anything else you need here, like send an email

        return $this->redirectToRoute('any_route');
    }

    return $this->render('registration/register.html.twig', [
        'form' => $form->createView(),
    ]);
}

Upvotes: 12

goodhand
goodhand

Reputation: 199

So, I found the error alas! I had set the field plainPassword in my UserType.php:

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('firstname', TextType::class)
        ->add('lastname', TextType::class)
        ->add('email', EmailType::class)
        ->add('birthdate', DateType::class)
        ->add('plainPassword', RepeatedType::class, array(
            'type' => PasswordType::class,
            'first_options'  => array('label' => 'Password'),
            'second_options' => array('label' => 'Repeat Password'),
        ))
        ->add('save', SubmitType::class, ['label' => 'Register']);
    }
...

Changing this to password like I have in my User entity corrects the error.

Thank you all for your help.

Upvotes: 0

Fovas Denis
Fovas Denis

Reputation: 23

The error seems that is in the twig file. You try to display the $plainPassword member, but it is not defined on the entity, most likely (in the begginning of my way to symfony, it happened a lot to have this error). Try to remove it and then check for the error.

As for the encoding of the password, please look at this url, as it explains how the passwords are encrypted in the security.yml file. You need to define the class that will be encoded, the algorithm can be changed for a custom one, that you can build and for this, please check this URL.

The encoding is not so complicated, but the error is not related to the encoding, so please try this and update the post.

Upvotes: 0

Thibault Henry
Thibault Henry

Reputation: 841

The problem is elsewhere.

Check in your twig or in your form if you call the "plainPassword" method, wich doesn't exists, and replace it by "password".

Upvotes: 0

Related Questions