Jump to content

[SOLVED] Allow users to set Forgot Password


hideaki

Recommended Posts

Hi guys,

 

The current default Prestashop Forgot Password flow is:

 

1. User clicks "Forgot your password?" link

2. User inputs their email address

3. User receives and email with a link and clicks

4. User receives another email with new password

5. User logs in with new password and change their password in "My Account"

 

Is it possible to reduce the 4th step so that when the user clicks the link in the first email they received, they would be able to change their password immediately instead of having to receive another email?

 

Thanks and all help is appreciated.

Edited by hideaki (see edit history)
Link to comment
Share on other sites

Hi guy,

 

A solution could be to send the new password in step 3, this would be possible by overriding PasswordController.

 

Else you have to securely make a link that 'allow' you to change password in step 3.

 

Hi math_php!

 

Thanks for your reply. I've made modifications to the PasswordController.php and here's what I have now:

 

PasswordController.php

  elseif (($token = Tools::getValue('token')) && ($id_customer = (int)(Tools::getValue('id_customer'))))
 {
  $email = Db::getInstance()->getValue('SELECT `email` FROM '._DB_PREFIX_.'customer c WHERE c.`secure_key` = "'.pSQL($token).'" AND c.id_customer='.(int)($id_customer));
  if ($email)
  {
   self::$smarty->assign(array('confirmation' => 1, 'token' => $token, 'id_customer' => $id_customer));
  }
  else
   $this->errors[] = Tools::displayError('We cannot regenerate your password with the data you submitted');
 }

 

password.tpl

{if isset($confirmation) && $confirmation == 1}
<form action="{$link->getPageLink('identity.php', true)}" method="post" class="std">
 <fieldset>
  <p class="password">
   <label for="passwd">{l s='New Password'}</label>
   <input type="password" name="passwd" id="passwd" />
  </p>
  <p class="password">
   <label for="confirmation">{l s='Confirmation'}</label>
   <input type="password" name="confirmation" id="confirmation" />
  </p>
  <p class="submit">
   <input type="submit" class="button" name="submitIdentity" value="{l s='Save'}" />
  </p>
 </fieldset>
</form>

 

However, I'm not able to set the password using my form. It turns out that

 

$customer = new Customer((int)(self::$cookie->id_customer));

 

does not get the id of the customer, even if i added a setcookie('id_customer', $id_customer); to the PasswordController.php. Please advice, thanks!

Link to comment
Share on other sites

Solved my own question. Here's the small hack should anyone require this feature in future:

 

In password.tpl, look for line (around 34):

 

{if isset($confirmation) && $confirmation == 1}

 

And insert after:

 

 <form method="post" class="std">
 <fieldset>
  <p class="password">
   <label for="passwd">{l s='New Password'}</label>
   <input type="password" name="passwd" id="passwd" />
  </p>
  <p class="password">
   <label for="confirmation">{l s='Confirmation'}</label>
   <input type="password" name="confirmation" id="confirmation" />
  </p>
  <p class="submit">
   <input type="submit" class="button" name="submitPass" value="{l s='Save'}" />
  </p>
 </fieldset>
</form>

 

 

In PasswordController.php, look for line (around 76):

 

if ($email)

 

Replace code inbetween (lines 78 - 101) with:

 

self::$smarty->assign(array('confirmation' => 1, 'token' => $token, 'id_customer' => $id_customer));

 

Again in PasswordController.php, look for line (around 41):

 

parent::process();

 

And insert after:

 

  if (Tools::isSubmit('submitPass'))
 {
  $token = Tools::getValue('token');
  $id_customer = Tools::getValue('id_customer');
  $email = Db::getInstance()->getValue('SELECT `email` FROM '._DB_PREFIX_.'customer c WHERE c.`secure_key` = "'.pSQL($token).'" AND c.id_customer='.(int)($id_customer));
  if ($email)
  {
   $customer = new Customer();
   $customer->getByemail($email);

   if ($_POST['passwd'] != $_POST['confirmation'])
   {
 $this->errors[] = Tools::displayError('Password and confirmation do not match');
   }
   else
   {
 $customer->passwd = Tools::encrypt($password = $_POST['passwd']);
 $customer->last_passwd_gen = date('Y-m-d H:i:s', time());
 if ($customer->update())
 {
  Tools::redirect('authentication.php');
 }
 else
 {
  $this->errors[] = Tools::displayError('An error occurred with your account and your new password cannot be changed. Please report your problem using the contact form.');
 }
   }
  }
  else
  {
   $this->errors[] = Tools::displayError('You cannot change your password with the data submitted');
  }
 }

 

Good luck to anyone trying this out!

  • Like 2
Link to comment
Share on other sites

  • 4 weeks later...
  • 1 month later...

This post did help me update my password recovery process, but I'd like to make some comments:

  1. The code does not check that the new password is a valid password according to Prestashop rules. This can result in a condition where a user sets an invalid password, it appears that everything worked correctly, but they can't log in because the password is invalid. A validation check on the new password is needed.
  2. Direct changes to the PasswordController should be avoided. If using Prestashop 1.4 or higher you can override functionality in the core by extending controllers in the override/controllers directory.
  3. The password recovery process is somewhat insecure (at least as of 1.4.9) as the secure key (token) and user id combination is always the same. This means that any person who has access to an old password reset email can reset the password for the user at any time that they wish. A secure key is inherently insecure after it has been sent in clear text over email (in the reset URL). Updating the secure key/token each time the password is reset might help make this process a bit more secure. Adding a security question or two to the user profile information that the user would have to answer correctly before updating the password would also help increase security.

Those are just some of my thoughts on this issue that might help others thinking about this.

  • Like 3
Link to comment
Share on other sites

  • 7 months later...
Those are just some of my thoughts on this issue that might help others thinking about this.

 

Hi, thanks all for this thread. I've just implemented a similar recovery process. Taking elameno remarks in consideration, before sending the email containing the url to change the password, I ask the user his last name. The token in the url is encrypted with AES and will change at each password change request.

 

When the user follows the url in the mail, I decrypt the token. It contains a time stamp so that I can deny an expired request (around 10 minutes). I ask again for the last name and then validate the new password according to PrestaShop rules using Validate::isPasswd($new_password).

 

 

Now I need a better hash function for storing the password in the database.

Edited by emily_d (see edit history)
Link to comment
Share on other sites

  • 5 months later...
  • 2 years later...

Any chance somebody can update this for latest prestashop (1.6.1.5) version?

 

Receiving plain text password in e-mail is very bad. I tried to apply modification from posts above but files have changed significantly since 1.4.

 

Edit: I tried this:

 

https://github.com/PrestaShop/PrestaShop/commit/863a2f264e461d03d7a230c50ed46e73ac015345#diff-83536235df8e0d38c1fdcfd4b2613a0cL191

 

but it says that there was an error while trying to recover password. I think it has something to do with token, because I cannot alter customers or add them at all.

 

customer (Unknown column 'reset_password_token' in 'field list')

 

Why isn't this update in the latest prestashop? It's so much better than plain text recovery. I think this should be added to main prestashop release.

Edited by Jurist (see edit history)
Link to comment
Share on other sites

I've actually managed to reset password function work as described here:

 

https://github.com/PrestaShop/PrestaShop/commit/863a2f264e461d03d7a230c50ed46e73ac015345#diff-83536235df8e0d38c1fdcfd4b2613a0cL191

 

I've just added missing fields in ps_customer table but now I cannot add new customer or register in front office. It says that there's a problem with object customer ()

 

Looks like some database alteration is needed to make this work.

 

Really don't understand why this is not in official release.

Link to comment
Share on other sites

Notice in Zeile 906 der Datei /home/dewetroomsdesign/public_html/classes/ObjectModel.php
[8] Undefined property: Customer::$reset_password_token

Notice in Zeile 906 der Datei /home/dewetroomsdesign/public_html/classes/ObjectModel.php
[8] Undefined property: Customer::$reset_password_validity

Notice in Zeile 352 der Datei /home/dewetroomsdesign/public_html/classes/ObjectModel.php
[8] Undefined property: Customer::$reset_password_token

Notice in Zeile 352 der Datei /home/dewetroomsdesign/public_html/classes/ObjectModel.php
[8] Undefined property: Customer::$reset_password_validity

 

Removing validation 

 

'reset_password_token' =>        array('type' => self::TYPE_STRING, 'validate' => 'isSha1', 'size' => 40, 'copy_post' => false),
            'reset_password_validity' =>    array('type' => self::TYPE_DATE, 'copy_post' => false),
 
from Customer.php solves the issue and makes password reset work. 
Edited by Jurist (see edit history)
  • Like 1
Link to comment
Share on other sites

  • 2 years later...
  • 6 months later...
 
 
 
On 4/18/2016 at 3:14 PM, Jurist said:

Hi @Jurist thanks for this link, I have applied these modifications but I have two problems now, I want to know if you had these problems too? if yes how did you solve it?

This is what I have commented on that commit:

 

I'm using PrestaShop 1.6.1.20. Before applying these changes, I have checked the process of password reset and it works correctly. After modifying files I'm facing two problems.

First one, when I fill in the email section and send a request for a password reset, it shows me the following error:
An error occurred while sending the email
but it sends the email, so it shows an error but the email was already sent.
 

The second problem is when I click on the email link, "new password" form will show up but when I fill the new password it shows the following error:
The password change request expired. You should ask for a new one.

It takes less than 20 seconds to do this process, so it shouldn't relate to the time issue I guess.
 

P.S: I couldn't apply modifies which starts with the install-dev directory. I couldn't find it (I'm using normal PrestaShop, not the Development version)

 

Thanks for responding.

Link to comment
Share on other sites

  • 9 months later...
On 4/18/2016 at 1:12 PM, Jurist said:

Removing validation 

'reset_password_token' =>        array('type' => self::TYPE_STRING, 'validate' => 'isSha1', 'size' => 40, 'copy_post' => false),
            'reset_password_validity' =>    array('type' => self::TYPE_DATE, 'copy_post' => false),
 
from Customer.php solves the issue and makes password reset work. 

Just wanted to say thanks for this, upgraded to 1.7 and had this issue and was driving me up the wall, adding this to customer.php worked for us too :)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...