Score:0

How do I migrate Yii2 passwords?

in flag
VVS

I migrated users from Yii2 to Drupal 9, where there are password hashes like $2y$13$nhBZ37OKp27jJBLgRkFlOuL5ac8Bda5n2XIZTjKON5gKPfIcxh61y genereated by Yii2 with \Yii::$app->security->generatePasswordHash("123qweASD")).

I migrated them 1:1.

Migrating users - advanced password examples says:

If the source system was a PHP based application that used crypt() or password_hash(), these hashes should work as-is and they can be migrated 1:1 like in the Phpass example above .When the user logs in to your Drupal 8 site for the first time, Drupal will re-hash the password.

The password are not correct.

I tried to manually insert various hashes into the database according to this algorithm (crypt() with costFactor 13) generated in Yii2, but this also leads to a login error.

I found the following code in Yii2 (User.php).

/**
 * Validates password
 *
 * @param string $password password to validate
 * @return boolean if password provided is valid for current user
 */
public function validatePassword($password)
{
    if(!$password) return false;
    return Yii::$app->security->validatePassword($password, $this->password);
}

In Security.php, it uses the following code.

/**
 * Verifies a password against a hash.
 * @param string $password The password to verify.
 * @param string $hash The hash to verify the password against.
 * @return boolean whether the password is correct.
 * @throws InvalidParamException on bad password/hash parameters or if crypt() with Blowfish hash is not available.
 * @throws InvalidConfigException when an unsupported password hash strategy is configured.
 * @see generatePasswordHash()
 */
public function validatePassword($password, $hash)
{
    if (!is_string($password) || $password === '') {
        throw new InvalidParamException('Password must be a string and cannot be empty.');
    }

    if (!preg_match('/^\$2[axy]\$(\d\d)\$[\.\/0-9A-Za-z]{22}/', $hash, $matches) || $matches[1] < 4 || $matches[1] > 30) {
        throw new InvalidParamException('Hash is invalid.');
    }

    switch ($this->passwordHashStrategy) {
        case 'password_hash':
            if (!function_exists('password_verify')) {
                throw new InvalidConfigException('Password hash key strategy "password_hash" requires PHP >= 5.5.0, either upgrade your environment or use another strategy.');
            }
            return password_verify($password, $hash);
        case 'crypt':
            $test = crypt($password, $hash);
            $n = strlen($test);
            if ($n !== 60) {
                return false;
            }
            return $this->compareString($test, $hash);
        default:
            throw new InvalidConfigException("Unknown password hash strategy '{$this->passwordHashStrategy}'");
    }
}

Yii 2.0.6 runs on PHP 5.6, while Drupal 9.4.5 runs on PHP 8.1.4.

How do I migrate password hashes?

id flag
Here is the check function: https://git.drupalcode.org/project/drupal/-/blob/9.4.x/core/lib/Drupal/Core/Password/PhpassHashedPassword.php#L221. Setting aside the documentation page for a moment, it is evident why a hash that begins with `$2y$13$` can't be checked.
VVS avatar
in flag
VVS
@cilefen Thx. How do I make this migration?
Score:3
in flag

That doc page seems to apply to Drupal 10, not Drupal 9. see: https://www.drupal.org/node/3322420

If you need to use Drupal 9 you could backport the code and/or write your own class the implements the same interface as

Drupal\Core\Password\PhpassHashedPassword

In Drupal 9 core.services.yml you wold need to swap your replacement class for that one in the core service definition.

service:
  password:
    class: Drupal\Core\Password\PhpassHashedPassword
    arguments: [16]

Altering is covered in the doc below, though there is a simpler way of using a replacement definition in the services file in sites/default/services.yml

https://www.drupal.org/docs/drupal-apis/services-and-dependency-injection/altering-existing-services-providing-dynamic-services

id flag
The documentation linked in the Question offers instructions for the same: https://www.drupal.org/docs/drupal-apis/migrate-api/migrate-destination-plugins-examples/migrating-users-advanced-password#s-preserving-passwords-hashed-with-another-algorithm
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.