I found this a really interesting problem recently. I wanted to migrate users from Magento to WordPress without forcing them to reset their password. You can’t export passwords for Magento or any well engineered web application, so the interesting part is migrating these passwords without ever knowing what the passwords are.
Quick Background for those not familiar with how Passwords are stored.
Problem:
If you store people’s passwords in your database (in plaintext), anyone who has or gets access to your database can read all those passwords (which may be reused other places).
Solution:
We don’t store passwords. Instead, we take the password and we do a bunch of math to it to get a gibberish string called a hash. So instead of storing a password like, “correct horse battery staple” we do a bunch of math to it (in the form of a function) and get c4bbcb1fbec99d65bf59d85c8cb62ee2db963f0fe106f483d9afa73bd4e39a8a
. There are lots of different hashing algorithms out there, in this case I used SHA-256 (the same hashing algorithm Magento uses).
Problem:
Some clever people started making a huge list of common passwords and the SHA-256 values they create. These lists are called Rainbow tables and allow you to take a hash, find it in a table, and see the plain text password it comes from.
Solution:
We add additional text to our password before we run it through our hashing alogrithm. This makes the Rainbow tables much larger and not practical. The additional text we add is called a “salt”.
How Magento Stores Passwords
At the very least, this is how the Magento install I was tasked with working with stored passwords.
A Magento password looks like this: 01d659e94e7d69481ba1a170cf9de69217705460ba028cfe5f5f0a6c59b5c24e:a7
In it you’ll notice the colon :
, while everything else is a digit or a letter from a-f (hexadecimal characters). The colon is acting as a separator. The characters before the colon are the hash (the result of our manipulating the plain text password with the SHA-256 algorithm). The characters after the colon are the salt (the extra text we add to the plain text before hashing, which we add to make it more difficult to determine the plain text password).
So if we take plain text password “correct horse batter staple” and put the salt “a7” on the front, then run it through our sha256 hashing algorithm, we get
01d659e94e7d69481ba1a170cf9de69217705460ba028cfe5f5f0a6c59b5c24e
Now this is a completely different hashing algorithm than the one used in WordPress but we can hook into the check_password
filter in WordPress and if the login is about to fail, we can check this alternate algorithm.
Unfortunately, we can’t store the Magento password in WordPress’s database table because it is 3 characters too long. Instead, we store it as User Meta.
Hooking into the WordPress Login Procedure
Once we have those pieces in place, we can add this code to hook into WordPress.
If a login is going to fail, we look for a user meta value containing a Magento hashed password belonging to the user (I’m using the key fe_magento_pwd
). If it exists, we break it into the salt and the hashed password. Then we use the plain text password the user typed in, hash it with the salt, and compare it with the sha256 hash stored in fe_magento_pwd
. If they match, we change the login check to true
.
If the password matches, I remove the User Meta fe_magento_pwd
and update the WordPress password to match the value that was typed in.
<?php | |
add_filter( 'check_password', 'fe_magento_check_password', 10, 4 ); | |
function fe_magento_check_password( $check, $password, $hash, $user_id ) { | |
if ( $check ) { | |
// the password is already accepted | |
// do nothing further | |
return $check; | |
} | |
// get user Magento password | |
$magento_pwd_parts = explode( | |
':', | |
get_user_meta( $user_id, 'fe_magento_pwd', true ) | |
); | |
if ( | |
! $magento_pwd_parts // the string exploded was empty | |
|| ! is_array( $magento_pwd_parts ) // result is not an array | |
|| ! sizeof( $magento_pwd_parts ) // the results are an empty array | |
) { | |
// exit early if we were unable to retrieve a Magento hashed password | |
// from User Meta | |
return $check; | |
} | |
$hash = $magento_pwd_parts['0']; | |
$salt = $magento_pwd_parts['1']; | |
if ( $hash === hash( 'sha256', $salt.$password ) ) { | |
// success, allow the user to log in | |
// update WordPress to use this password | |
wp_set_password( $password, $user_id ); | |
// delete Magento password User Meta | |
delete_user_meta( $user_id, 'fe_magento_pwd' ); | |
return true; | |
} | |
return $check; | |
} |
If others have a different perspective or a more elegant way to address this situation, I’d love to hear your thoughts in the comments below.
hi sal
great article, would love your help with something, I have a magento install, im migrating to WooCommerce, I had a plugin who got the magento hash, also in a csv file, but the password don’t seem to work, any idea on how to make it work ?
I think the data is already in the database, but just adding a function to the theme will fix this ?
thanks a lot
Hi lotfi,
The general idea is you’re intercepting the login process (using the
check_password
filter) and checking the entered password against the hashed Magento password you have in your database.If you get stuck, I am available for WordPress Magento Password consulting as part of the work I do under my company name, Iron Code Studio.
Just used this (adapted somewhat to suit my situation) and wanted to say thanks! Saved me a lot of time.
Hello there. This could potentially be a huge time saver and a face saver for us, as we are moving our users between these two platforms, but would like to make sure to have all the info we need before proceeding.
Do we use this code as a standalone file after users are imported (and how?) or do we add this to functions.php of our child theme?
Your help is HIGHLY APPRECIATED.
Hi Tomislav,
You’ll need to migrate your users from Magento to WordPress and store the hashed Magento password in the WordPress user meta table.
The code in this article needs to be run in the context of WordPress, there are a number of places you can add this code (you might want to see my post on different places to add WordPress code).
If you’re looking for further support I am available for WordPress consulting work under my company name, Iron Code Studio.
Best of luck.