I’m working on an application using Symfony 4.3. I’m currently working on a function to modify a user’s password and in order to do so I’m first verifying that the user knows his password before changing it. I’m doing this by typing the value of his current password in a form type. However, the php password_verify
function doesn’t seem to recognize the user’s actual password when he wants to change it. I’m using the symfony form builder which allows me to get values without explicitly setting them myself. We are able to recuperate the user’s password correctly and the hash but the function always returns false. I’m using the ‘auto’ algorithm to encrypt the passwords in security.yaml
.
I have tried everything, from using single quotes to double quotes, from using plain text for both the word password and the encoded version of it like so:password_verify('password','encoded_version')
or using the function dynamically. Below is some code which I have written. As previously stated I’m using the symfony form builder.
FORM TO ENTER THE PASSWORD
class PasswordUpdateType extends AbstractType
{
/**
* Permet d'avoir la configuration d'un chanmp
*
* @param string $label
* @param string $placeholder
* @return array $options
* @return array
*/
private function getConfiguration($label, $placeholder, $options = []) {
return array_merge([
'label' => $label,
'attr'=>[
'placeholder'=>$placeholder
]
], $options);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('oldPassword', PasswordType::class, $this->getConfiguration("Ancien mot de passe","Saisier le mot de passe actuel"))
->add('newPassword', PasswordType::class, $this->getConfiguration("Nouveau mot de passe","Saisier le mot de passe actuel"))
->add('confirmPassword', PasswordType::class, $this->getConfiguration("Confirmer le mouveau mot de passe","Saisier le mot de passe actuel"))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => PasswordUpdate::class,
]);
}
}
CODE TO VERIFY THAT THE PASSWORDS MATCH
public function updatePassword(Request $request, UserPasswordEncoderInterface $encoder, ObjectManager $manager) {
$passwordUpdate = new PasswordUpdate();
$user=$this->getUser();
$form = $this->createForm(PasswordUpdateType::class, $passwordUpdate);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
if(!password_verify($passwordUpdate->getOldPassword(),$user->getPassword())) {
$form->get('oldPassword')->addError(new FormError("Le mot de passe saisi n'est pas le mot de passe actuel"));
//dump($passwordUpdate->getOldPassword());
//dump(password_verify($passwordUpdate->getOldPassword(),$user->getPassword()));
dump($passwordUpdate->getOldPassword());
dump($encoder->encodePassword($user,$passwordUpdate->getOldPassword()));
dump(gettype($user->getPassword()));
dump(password_get_info($passwordUpdate->getOldPassword()));
die();
}
I’m constantly falling in the condition where the passwords do not match although my dumps are working which means the information is being recuperated. Thanks!
2
Answers
Use the
UserPasswordEncoder
Class see https://symfony.com/doc/current/security.html#c-encoding-passwordsSymfony has a constraint to verify current password in a submitted form: UserPassword
You can follow the documentation and add a dedicated
$oldPassword
to your user entity with this constraint, or you can add it directly to the form type, like so:Note that Symfony also has a constraint to check that two inputs are identical (e.g. “confirm password” field): RepeatedType. Consider using these two constraints instead of manually validating user input in your controller.