1

We imported a list of customers, which contained cleartext passwords from an old database (yes, believe me I understand how terrible it is to think they were stored as cleartext).

After the users have logged in at least once, then the Magento CE 1.9 reset system works like a charm. Also it works fine for new accounts that are created online, or in the admin.

The problem only exists for those that were imported, but have never logged in since the migration to Magento. After they click "Forgot your password" from the Magento Login page, they are asked to enter their email, and after they do, they receive an email with a link to go reset the password.

However, after they enter and confirm their new password, the system tells them that the link they used has already expired. This should not be the case, because I have the link expiry set to a full day, but the error occurs even when completing the process in less than 10 minutes.

Is it a password hash/salt problem? I assume so, since it works for imported users that had previously signed in (therefore correctly encrypting their passwords).

2 Answers 2

3

_validateResetPasswordLinkToken in the Account Controller:

$customerToken = $customer->getRpToken();
if (strcmp($customerToken, $resetPasswordLinkToken) != 0 || $customer->isResetPasswordLinkTokenExpired()) {
    throw Mage::exception('Mage_Core', $this->_getHelper('customer')->__('Your password reset link has expired.'));
}

Which in turn calls: isResetPasswordLinkTokenExpired

/**
 * Check if current reset password link token is expired
 *
 * @return boolean
 */
public function isResetPasswordLinkTokenExpired()
{
    $resetPasswordLinkToken = $this->getRpToken();
    $resetPasswordLinkTokenCreatedAt = $this->getRpTokenCreatedAt();

    if (empty($resetPasswordLinkToken) || empty($resetPasswordLinkTokenCreatedAt)) {
        return true;
    }

    $tokenExpirationPeriod = Mage::helper('customer')->getResetPasswordLinkExpirationPeriod();

    $currentDate = Varien_Date::now();
    $currentTimestamp = Varien_Date::toTimestamp($currentDate);
    $tokenTimestamp = Varien_Date::toTimestamp($resetPasswordLinkTokenCreatedAt);
    if ($tokenTimestamp > $currentTimestamp) {
        return true;
    }

    $dayDifference = floor(($currentTimestamp - $tokenTimestamp) / (24 * 60 * 60));
    if ($dayDifference >= $tokenExpirationPeriod) {
        return true;
    }

    return false;
}

SUGGESTIONS

Double check server time and Magento time zones.

It may be wise to batch the old plaintext passwords and update them to a more standard Magento password to be safest as well.


EDIT

Instead of reinventing the wheel a quick google search turned up a possible candidate to reset the passwords. Source: http://www.christopherhogan.com/2012/02/01/script-to-reset-all-customer-passwords-in-magento/

<?php
/************************
 *    / '_ __/_   _/_
 * ()()/(-( /( ()(/(-
 *   _/              
 *       since 2007
 *
 * Created by Foundco
 * All rights reserved unless otherwise specified under contract.
 * http://www.foundco.com/
 * @author Christopher Hogan <mailing address removed>
 * @copyright 2012 and beyond.
 ******************************/


error_reporting(E_ALL | E_STRICT);
$mageFilename = 'app/Mage.php';
if (!file_exists($mageFilename)) {
    echo $mageFilename." was not found";
    exit;
}
require_once $mageFilename;
Varien_Profiler::enable();
Mage::setIsDeveloperMode(true);
ini_set('display_errors', 1);
umask(0);
Mage::app(); 

$passwordLength = 10;

/****
  If you are just resetting one customer by customer_id:
****/

//$customer_id = 10;
//$customers = Mage::getModel('customer/customer')->getCollection()->addAttributeToFilter('entity_id', array('eq' => $customer_id));

/****
  If you are resetting all customers:
****/

$customer_id = 10;
$customers = Mage::getModel('customer/customer')->getCollection();

/****
  Now loop through the customers and create the passwords
****/

foreach ($customers as $customer){
    // $customer->generatePassword($passwordLength)
    // $customer->sendNewAccountEmail();
        $password = strtoupper(substr( $customer->getEmail(), 0, 3)).rand(111,999);
        $customer->setPassword($password)->save();
        $line_data = $customer->getEmail(). "\t". $customer->getPassword();
        $line[] = $line_data;
        echo $line_data."\n";
}
$content = implode("\n", $line);

// store all the passwords to a file:
file_put_contents('./accounts.csv', $content);
echo "COMPLETE!";
?>
3
  • Can you suggest a method to accomplish this "batch the old plaintext passwords and update them to a more standard Magento password"? Jun 23, 2014 at 5:01
  • Update my answer with reply.
    – B00MER
    Jun 24, 2014 at 14:52
  • Thanks for linking that script to reset all passwords. I had come across that already, and I am keeping in in my back pocket as a last measure. I'm trying to keep this transition as seamless as possible, and would really like to maintain the users passwords as they were. I tested again with an imported user. When they have never logged in, the isResetPasswordLinkTokenExpired passes, and the user sees the notice that the link has expired. But, logging in (with the right password) fixes the issue. So I need to find a script to just log in/out all customers using known password. Jun 25, 2014 at 5:53
0

The issue can be related to template file. In my case when i was updating the password it was showing the error "your password reset link has expired."

If this the case, Please go to /app/design/frontend/base/default/template/customer/form/resetforgottenpassword.phtml

if the form shows like this:

<form action="<?php echo $this->getUrl('*/*/resetpasswordpost'); ?>" method="post" id="form-validate">

replace it with:

<form action="<?php echo $this->getUrl('*/*/resetpasswordpost', array('_query' => array('id' => $this->getCustomerId(), 'token' => $this->getResetPasswordLinkToken()))); ?>" method="post" id="form-validate">

Then try to reset the password.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.