<p>That approach is not going to work.</p>
<p>Due to how Craft handles passwords internally when saving a new user, the hashed password in your Element API feed actually end up being hashed again (as Craft treats it as a new password, i.e. implicitly un-hashed). Hence, your imported users' passwords in the <code>users</code> database table will actually be <em>hashes of the original hashes</em>, which is why the original, raw password won't match.</p>
<p>I don't think there's a way to work around this, so if requiring users to create new passwords is off the table, your only option is to <em>somehow replace the double-hashed <code>password</code> columns in the <code>users</code> table, with the original hashed passwords from your feed, after the users have been imported</em>. If this is a one-time import and the number of users isn't too high, that could be done manually by simply replacing the hashes in the <code>users</code> table's <code>password</code> column with the original hashes.</p>
<p>Another option is to create a <a href="https://craftcms.com/docs/4.x/extend/migrations.html#creating-migrations" rel="nofollow noreferrer">content migration</a> that runs after the users have been imported; that migration could read in the same feed as Feed Me does, looping over each row and querying (by username or email) for a matching user. Then, if a matching user is found, the migration could execute a custom database query to update the value in the <code>password</code> column with the original hash from the feed.</p>
<p>A different approach entirely, is to not include the passwords in the Feed Me feed, and to use something like the <a href="https://plugins.craftcms.com/legacy-login?craft4" rel="nofollow noreferrer">Legacy Login plugin</a> to provide a way for imported users to log in using their original passwords (the original passwords can be kept in a separate database table, or a different database altogether).</p>

CC BY-SA 4.0
2023-05-19T12:53:10.657Z
Thank you. I'll look at the content migration solution, as manual edition or database + plugin solution does not fit for my project.
Romain P.
CC BY-SA 4.0
2023-05-19T12:30:13.733Z
2023-05-19T12:39:57.370Z
2023-05-19T12:39:57.370Z
Mats Mikkel Rummelhoff
<p>I'm trying to move a large batch of users from a Craft 3 to a separate Craft 4 websites (only some selected data should be migrated).</p>
<p><a href="https://github.com/craftcms/element-api" rel="nofollow noreferrer">Element API</a> + <a href="https://github.com/craftcms/feed-me" rel="nofollow noreferrer">FeedMe</a> looks like the right solution for that, as Element API comes with transformer, and FeedMe comes with field mapping and a queue system for imports.</p>
<p>Following <a href="https://craftcms.stackexchange.com/questions/30675/move-users-with-feed-me">this question</a>, it looks like possible to migrate the users' passwords. This is how I got this in Element API (passwords are hashed):</p>
<pre><code>return [
    'elementType' =&gt; User::class,
    'transformer' =&gt; function(User $user) {
        $user = User::find()
            -&gt;addSelect(['users.password'])
            -&gt;id($user-&gt;id)
            -&gt;one();

        return [
            'firstName' =&gt; $user-&gt;firstName,
            'lastName' =&gt; $user-&gt;lastName,
            'password' =&gt; $user-&gt;password
        ];
    },
];
</code></pre>
<p>However, even if the passwords are mapped by FeedMe, the users can't log in with their initial password, probably because of the hash. Why and how to make their passwords working on their migrated accounts?</p>
<p>If it would never work this way (example: because of hash securities), what would be the alternative?</p>
<p>I know I could ask users to request a new password on the new Craft 4, but this is not the solution I'm looking for.</p>

<users><plugin-elementapi><plugin-feedme><migration><password>
How to migrate a selection of users passwords from a Craft 3 to a separate Craft 4?
# How to migrate a selection of users passwords from a Craft 3 to a separate Craft 4?

(Asked by: username_0 on 2023-05-19)

I'm trying to move a large batch of users from a Craft 3 to a separate Craft 4 websites (only some selected data should be migrated).
Element API + FeedMe looks like the right solution for that, as Element API comes with transformer, and FeedMe comes with field mapping and a queue system for imports.
Following this question, it looks like possible to migrate the users' passwords. This is how I got this in Element API (passwords are hashed):
return [
    'elementType' => User::class,
    'transformer' => function(User $user) {
        $user = User::find()
            ->addSelect(['users.password'])
            ->id($user->id)
            ->one();

        return [
            'firstName' => $user->firstName,
            'lastName' => $user->lastName,
            'password' => $user->password
        ];
    },
];

However, even if the passwords are mapped by FeedMe, the users can't log in with their initial password, probably because of the hash. Why and how to make their passwords working on their migrated accounts?
If it would never work this way (example: because of hash securities), what would be the alternative?
I know I could ask users to request a new password on the new Craft 4, but this is not the solution I'm looking for.

**Tags:** users, plugin-elementapi, plugin-feedme, migration, password

---

## 1 answers

### Answer by username_1 on 2023-05-19. Score: 2

That approach is not going to work.

Due to how Craft handles passwords internally when saving a new user, the hashed password in your Element API feed actually end up being hashed again (as Craft treats it as a new password, i.e. implicitly un-hashed). Hence, your imported users' passwords in the `users` database table will actually be *hashes of the original hashes*, which is why the original, raw password won't match.

I don't think there's a way to work around this, so if requiring users to create new passwords is off the table, your only option is to *somehow replace the double-hashed `password` columns in the `users` table, with the original hashed passwords from your feed, after the users have been imported*. If this is a one-time import and the number of users isn't too high, that could be done manually by simply replacing the hashes in the `users` table's `password` column with the original hashes.

Another option is to create a [content migration](https://craftcms.com/docs/4.x/extend/migrations.html#creating-migrations) that runs after the users have been imported; that migration could read in the same feed as Feed Me does, looping over each row and querying (by username or email) for a matching user. Then, if a matching user is found, the migration could execute a custom database query to update the value in the `password` column with the original hash from the feed.

A different approach entirely, is to not include the passwords in the Feed Me feed, and to use something like the [Legacy Login plugin](https://plugins.craftcms.com/legacy-login?craft4) to provide a way for imported users to log in using their original passwords (the original passwords can be kept in a separate database table, or a different database altogether).

> **Comments:**
> **username_0**: Thank you. I'll look at the content migration solution, as manual edition or database + plugin solution does not fit for my project.  

---

