0

We are migrating our old site from plain PHP to Drupal 8. Passwords are hashed with MD5 in the old site; I need to migrate them in Drupal.

I tried the following code, but it takes the password as plain text and calculates its SHA hash.

public function prepareRow(Row $row) {
    $password = $row->getSourceProperty('user_password');
    $hash = \Drupal::service('password')->hash($password);
    $row->setSourceProperty('user_password', $hash);
  }

This is the configuration file.

id: users
label: User migration
migration_group: mymodule_general_migration_groups
source:
  plugin: mymodule_migration_users
process:
  pass: user_password
  mail: user_email
  init: user_email
  status:
    plugin: default_value
    default_value: 1
  name:
    plugin: dedupe_entity
    source: username
    entity_type: user
    field: name
    postfix: _
  created:
    plugin: callback
    source: created
    callable: strtotime
  changed: user_regdate
  access: user_regdate
  login: user_lastvisit
destination:
  plugin: entity:user
  md5_password: true
migration_dependencies: {}
dependencies:
  enforced:
    module:
      - mymodule_migration
9
  • Please try this first drupal.org/docs/8/api/migrate-api/… and if those do not work for you provide a more detailed explanation on which steps you have ran so far
    – d70rr3s
    Jan 24, 2020 at 7:15
  • Already went through this. It doesn't show how to decrypt md5 to plain text and convert them into hash. Do you get my point?
    – Souvik Das
    Jan 24, 2020 at 7:17
  • 1
    You cannot decrypt MD5 directly quora.com/Is-this-possible-to-decrypt-MD5 what you can is to reset all your users password and send a one-time-login password to them once they are migrated.
    – d70rr3s
    Jan 24, 2020 at 7:24
  • 1
    I mean that you cannot obtain the original password (plain text) in order to re-hash it using your current mechanism. Typically you would do this drupal.org/docs/8/api/migrate-api/… but if this is not working for you as you metion in your comments, perhaps you could provide more information on why this does not works for you.
    – d70rr3s
    Jan 24, 2020 at 7:32
  • 1
    Yes, @d70rr3s is correct: Functions like hash() don't encrypt text, but calculate the hash value, and by definition they are one-way functions. (It means there aren't inverse functions that from the hash return the original value.)
    – apaderno
    Jan 24, 2020 at 8:39

2 Answers 2

3

Since you don't know the password, only the hash, you can't migrate it directly. (MD5 is weak, but not that weak.) The whole purpose of hashing is that the password should be unknown to anyone except the user. There are 2 solutions to this.

  • Reset all your users password and send a one-time-login password to them once they are migrated - as already suggested in the comments above.
  • Write custom code that rehashes the password at login: "If the password is hashed with MD5, rehash it and store the hash when the user (successfully) logs in." This works because at login you have the user's password because they just entered it. And you know which hashing algorithm is used from the stored hash.Initially, you migrate the users with the MD5 password hash.

It turns out that Drupal does rehashing automatically (see UserAuth::authenticate()), but not for MD5 unless you modify the existing hash slightly by prefixing it with an "U". (Thanks, d70rr3s and Souvik Das.) See also user_update_7000.

7
  • 1
    The second option could lead to security problems, since an attacker could try to login with a wrong password and get instant access. The first option is at the best if using this drupal.org/docs/8/api/migrate-api/… does not work for the use case.
    – d70rr3s
    Jan 24, 2020 at 7:50
  • Sorry, but there is no security problem. You of course validate the password before storing the rehashed password. If you provide the wrong password nothing happens.
    – hansfn
    Jan 24, 2020 at 7:56
  • You mean storing the old hashed password on another field, flagging the user so you you need to intervine the login process, that would be the way. That should be clarified in your answer. You could improve it with that example.
    – d70rr3s
    Jan 24, 2020 at 8:07
  • 1
    @d70rr3s: No, you don't need to flag anything. The hash itself reveals if it is a MD5 hash or hashed with Phpass - the current Drupal hashing algorithm. In other words, you migrate the MD5 hash as is, and then rehashes at login. Anyway, this is a lot more work than just resetting ... (Will update the answer slightly.)
    – hansfn
    Jan 24, 2020 at 8:21
  • 3
    @hansfn you are totally right if fact it seems is already supported by core, this the method used \Drupal\user\UserAuth::authenticate and checks if the password needs rehashing, so no further action is needed.
    – d70rr3s
    Jan 24, 2020 at 8:34
1

This simple code is working properly while migrating md5 password to drupal 8

$password_service = \Drupal::service('password');

  $password = $row->getSourceProperty('user_password'); // 'user_password' is the old db column which is in md5 format

  $hashed_password = 'U' . $password_service->hash($password); // U will indicate that the password needs rehashing.
  $row->setSourceProperty('hash_password', $hashed_password);

Your Answer

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

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