Search code examples
phpsymfonysymfony4change-password

Why isPasswordValid() function always return false?


I am working on a simple reset password system with Symfony4.

I don't know why isPasswordValid() always return false?

I am using Bcrypt to Hash the password Here is some code of Security.yaml :

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

I don't know why isPasswordValid() Always returns false. I manually tried this:

$pass="000000000";
dump($encoder->isPasswordValid($user, $pass));
die();

and it dump false..

Here is the function I wrote on the controller:

/**
 * @Route("/password", name="change_pass", methods={"GET","POST"})
 * @IsGranted("ROLE_USER")
 */
public function edit(Request $request,UserPasswordEncoderInterface $encoder): Response
{

    $user = $this->getUser();

    $form = $this->createForm(ResetPassType::class, $user);
    $form->handleRequest($request);

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

        $oldPassword = $request->request->get('reset_pass')['oldPassword'];
        $newPassword = $user->getPassword();

        if ($encoder->isPasswordValid($user, $oldPassword)) {
            $hash = $encoder->encodePassword($user,$newPassword);
            $user->setPassword($hash);
            $this->getDoctrine()->getManager()->flush();
            $this->addFlash('success', 'Your password is succesfully changed');
        }else {
            $this->addFlash('fail', 'old password is wrong');
        }

    }
    $this->getDoctrine()->getManager()->refresh($user);

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

Here is the form ResetPassType :

   public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('oldPassword', PasswordType::class, [
            'mapped' => false,])
        ->add('password',PasswordType::class)
        ;
    }

Solution

  • Short answer: you are using the new password as the old password's hash.


    Explanation:
    I guess you bound your form to your user class. The password field in your form is mapped, meaning it updates your user's password property.

    Therefore, as the property should contain the hash of the "old password" but contains your new password, it can't validate.


    Solution and improvements:
    The quickest solution would be to "unmap" the password field or to remove the data_class form option, and to replace a line in your controller:

    // before: $newPassword = $user->getPassword();
    $newPassword = $form->get('password')->getData();
    

    I'd suggest to:

    • unbind the form to your user class
    • use the UserPassword validation constraint for your oldPassword field
    • fetch the form data using $form->getData() instead of accessing the $request manually