Import customers with hashed passwords into Magento 2

Import customers into Magento 2.

Whether you are migrating your site from Magento 1, or from another platform, like WordPress, Prestashop, Symfony… you likely have a customer database you are interested in migrating to your new Magento 2 site. Once you have imported customers to Magento 2 with personal data, hashed passwords, addresses, etc.. If you have not taken into account the change of the Magento 2 encryption in passwords, you will face problems:

Import customers with hashed passwords into Magento 2. Magento 2 Login
Import customers with hashed passwords into Magento 2. Login
Import customers with hashed passwords into Magento 2. Magento 2 Login Error
Import customers with hashed passwords into Magento 2. Login Error

Magento 2 customer password.

Magento 2 has changed how the customer passwords are stored, the password hash method. It still supports the MD5 encryption method,. However, if you are not using an integration tool to import your customers, they might have to reset their password on their next login to your store… Really?

The reason is that Magento 2 customer encryption it is not a simple MD5 hash, it contains a salt, and a salt version. Therefore your customers cannot be authenticated with MD5 hash algorithm by default.

Link to Magento 2 core

Magento 2 : {password}:{salt}:{hash version}

Magento 1 : {password}:{salt}

In the image below you can see MD5 hashed passwords, and the new Magento 2 format, that is much longer, and it is structured in three parts.

Import customers with hashed passwords into Magento 2. Magento 2 MD5 hash
Import customers with hashed passwords into Magento 2. MD5 hash

The solution

No worries, your customers won’t need to reset their passwords again. You can write a simple module to extend the Magento 2 authentication method.

1. Write a Plugin

First of all, we create a Plugin \Magento\Customer\Model\ AccountManagement with a Before method to extend the  authenticate($customerId, $password) 

Eg.

<type name="Magento\Customer\Model\AccountManagement">
 <plugin 
 name="JokiRuiz_LegacyAuthentication_AuthenticationPlugin"
 type="JokiRuiz\LegacyAuthentication\Plugin\AuthenticationPlugin" 
 />
</type>
/**
* @param AccountManagement $subject
* @param $username
* @param $password
*/
public function beforeAuthenticate(
    AccountManagement $subject,
    $username,
    $password
) {
    if($this->_dataHelper->isEnabled()) {
        $this->_authenticatePasswordRequest($username,$password);
    }
}

2. Add Configurations to store the old salt and enable/disable the module

Import customers with hashed passwords into Magento 2. Magento 2 Configure Salt
Import customers with hashed passwords into Magento 2. Configure Salt
<section id="jokiruiz_legacyauthentication"
showInDefault="1" showInStore="1" showInWebsite="1" sortOrder="10" translate="label">
    <label>Legacy Authentication</label>
    <tab>jokiruiz</tab>
    <resource>JokiRuiz_LegacyAuthentication::config</resource>
    <group id="general" showInDefault="1" showInStore="1" 
    showInWebsite="1" sortOrder="10" translate="label">
        <label>General</label>
        <field id="enabled" showInDefault="1" showInStore="1" 
        showInWebsite="1" sortOrder="10" translate="label" 
        type="select">
           <label>Enable MD5 Authentication</label>
           <comment/>
           <source_model>Magento\Config\Model\Config\ 
           Source\Enabledisable</source_model>
        </field>
        <field id="md5_salt" showInDefault="1" showInStore="1" 
        showInWebsite="1" sortOrder="10" translate="label" 
        type="text">
            <label>MD5 Salt</label>
            <comment>Leave empty if salt is not used</comment>
        </field>
    </group>
</section>

 3. And finally, write the code the compatibility 😉

This example below will make it compatible with Prestashop, that is md5( COOKIE_KEY + password). But below you can put here whatever legacy encryption you need to make Magento 2 compatible.

/**
* @param $username
* @param $password
* @throws InvalidEmailOrPasswordException
*/
private function 
    _authenticatePasswordRequest($username,$password)
{
    ...
    $md5Hash = $customerSecure->getPasswordHash();
    if (strlen($md5Hash) == self::MD5_HASH_LENGTH) {
        $md5Salt = $this->_dataHelper->getSalt();
        if ($md5Salt) {
            $password = $md5Salt.$password;
        }
        if ($md5Hash === md5($password)) {
            return true;
        }
        throw new InvalidEmailOrPasswordException(
            __('Invalid login or password.'));
    }
...
}

We have to make our Magento 2 compatible with the old encryption system. But by doing this you are making your Magento 2 less secure… so this has to be temporal solution. Ideally, we have this system until the majority of our customers have logged in the new system, and then we won’t need it anymore… How?

To do that, the strategy is going to be to update the password hashes from the old encryption to the new system. Therefore, we let the customer to login in ‘legacy mode’ the first time. But when the login is succeed, we generate the new Magento 2 hashed to replace it. At this point, we have the original password of the customer, so we can hash it in the Magento 2 way :).

...
if (strlen($md5Hash) == self::MD5_HASH_LENGTH &&
    $paIsPasswordPatched->getValue() != '1') {
    if ($this->_authenticateMd5Password($customerSecure,  
        $password)) {
        $customer->setCustomAttribute
            ('jr_is_password_patched', 1);
        $customerSecure->setPasswordHash
            ($this->createPasswordHash($password));
        $this->_customerRepository->save($customer);
    }
    else {
        throw new InvalidEmailOrPasswordException(
            __('Invalid login or password.'));
    }
}
...

Have you face this problem? Do you have a different solution? Maybe you couldn’t make it by following my steps? I’m very happy to get your feedback! You can contact me or write a comment below.

Happy coding!

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x