Did you display the old password in the password form field ? in this case it could be displayed encrypted and thus encrypted a second time on saving.
Hashes are typically not decypherable, so you should not display the password on a field.
This is a common problem when working with sfGuard. Here are 2 solutions, there is probably others that will answer this issue :
- Do not let user changer user's password in this form and create a separate form for password reset
- Let password form field empty by default, and save it only when the user types in a new password
I usually get into the second way, here is the form class used :
class ewaSfGuardUserForm extends sfGuardUserForm
{
public function configure()
{
// parent::configure();
//"virtual" new password fields, empty by default
$this->widgetSchema['new_password'] = new sfWidgetFormInputPassword();
$this->widgetSchema['new_password_bis'] = new sfWidgetFormInputPassword();
$error_messages = array('min_length' => 'Passwords must be at least 4 characters long.');
$this->validatorSchema['new_password'] = new sfValidatorString(array('required' => false, 'min_length' => 4), $error_messages);
$this->validatorSchema['new_password_bis'] = new sfValidatorString(array('required' => false, 'min_length' => 4), $error_messages);
$error_messages = array('invalid' => 'New password didn\'t match confirmation');
//validate identical password
$this->validatorSchema->setPostValidator(new sfValidatorSchemaCompare('new_password', '==', 'new_password_bis', array(), $error_messages));
$this->validatorSchema->setPostValidator(
new sfValidatorAnd(array(
new sfValidatorDoctrineUnique(array('model' => 'sfGuardUser', 'column' => array('email_address'))),
new sfValidatorDoctrineUnique(array('model' => 'sfGuardUser', 'column' => array('username')), array('invalid' => 'Email is already in use for another account')),
new sfValidatorSchemaCompare('new_password', '==', 'new_password_bis', array(), $error_messages)
))
);
//unused fields
unset(
$this['groups_list'],
$this['permissions_list'],
$this['password'],
$this['created_at'],
$this['updated_at'],
$this['last_login'],
$this['salt'],
$this['algorithm']
);
//putting back validator for real password field
$this->validatorSchema['password'] = new sfValidatorPass();
}
}
The other part is in action class sf_guard_userActions
protected function processForm(sfWebRequest $request, sfForm $form)
{
$requestParams = $request->getParameter($form->getName());
$requestParams['password'] = $requestParams['new_password'];
$requestParams['email_address'] = $requestParams['username'];
$form->bind($requestParams, $request->getFiles($form->getName()));
if ($form->isValid())
{
[....] Copy of generated code
}
}
The specificity of my implementation is it always force uses email == username.
I do not use an extended model for storing user's profile, but I override defaut sfGuardUser doctrine table to add extra fields like first name, last name, etc. It works this way, perhaps doctrine inheritance would have been better.