Migrating users

Last updated on
25 April 2025

The migrate destination plugin entity:user lets you migrate users. The tricky part of user migration is preserving the passwords. Besides passwords, everything else is just standard field mapping in a process pipeline.

Migrating MD5 hashed passwords

Drupal 6 and many other older systems use MD5 algorithm for password hashing. These password hashes must be migrated to Drupal 8 using  the md5_passwords: true configuration option so that the users can use their old passwords. If your migration is based on d6_user.yml, then md5_passwords:true is already enabled. The passwords are salted and re-hashed before they are saved into the destination database. 

destination:
  plugin: entity:user
  md5_passwords: true

The example below uses the EmbeddedDataSource source plugin for the sake of simplicity. The MD5 hash in the example is a hash of 'password'.;

id: custom_user_migration
label: Custom user migration
source:
  plugin: embedded_data
  data_rows:
    -
      user_id: 1
      name: johnsmith
      mail: johnsmith@example.com
      pw_hash: 5f4dcc3b5aa765d61d8327deb882cf99
      status: 1
  ids:
    user_id:
      type: integer
process:
  name: name
  mail: mail
  pass: pw_hash
  status: status
destination:
  plugin: entity:user
  md5_passwords: true

Migrating plain text passwords

If the passwords are plain text in the source, you can preserve the passwords by processing them through md5 during the migration using the Callback process plugin and then using the md5_passwords: true configuration option as in the previous example.

id: custom_user_migration
label: Custom user migration
source:
  plugin: embedded_data
  data_rows:
    -
      user_id: 1
      name: johnsmith
      mail: johnsmith@example.com
      pw_plain: super-secret-password
      status: 1
  ids:
    user_id:
      type: integer
process:
  name: name
  mail: mail
  pass:
    plugin: callback
    callable: md5
    source: pw_plain    
  status: status
destination:
  plugin: entity:user
  md5_passwords: true

Advanced password hash migration examples

Examples for more advanced password hash migrations.

 Ignoring user 1 during migration (skip_on_value plugin)

User 1 exists in our destination site, so we do not need to migrate it from the source site. The example below uses the skip_on_value plugin to do this. The example is based on the version of d7_user.yml generated using the Migrate Plus module.

The value key accepts an array. So if we wanted to ignore users 2, 9, and 20 we could list their user IDs:
value:
   - 2
   - 9
   - 20

The same strategy can be used to ignore node IDs using nid

langcode: en
status: true
dependencies: {  }
id: upgrade_d7_user
class: Drupal\user\Plugin\migrate\User
field_plugin_method: null
cck_plugin_method: null
migration_tags:
  - 'Drupal 7'
  - Content
migration_group: migrate_drupal_7
label: 'User accounts'
source:
  plugin: d7_user
process:
  uid:
    -
      plugin: skip_on_value
      equals: true
      source: uid
      method: row
      value:
        - 1
  name:
    -
      plugin: get
      source: name
  pass:
    -
      plugin: get
      source: pass

  mail:
    -
      plugin: get
      source: mail
  created:
    -
      plugin: get
      source: created
  access:
    -
      plugin: get
      source: access
  login:
    -
      plugin: get
      source: login
  status:
    -
      plugin: get
      source: status
  init:
    -
      plugin: get
      source: init
destination:
  plugin: 'entity:user'
migration_dependencies:
  optional:
    - upgrade_user_picture_field_instance
    - upgrade_user_picture_entity_display
    - upgrade_user_picture_entity_form_display

Migrating roles

You can migrate roles, see #3211976-2: migrate users into groups by role for more details. process: field_company included to show structure, and where to place the  roles-part:

process:
  field_company: company

  roles:
    -
      plugin: static_map
      bypass: true
      source: role
      map:
        admin: administrator
        member: validated
        'NULL': anonymous
        '': anonymous
        transform: validated

List of user properties

In addition to the 'name', 'mail', 'pass', and 'status' properties used in the examples, the following properties are available on the user entity.

  • uid, leave this out if you want Drupal to generate the unique user IDs for the migrated users
  • langcode
  • preferred_langcode
  • preferred_admin_langcode
  • timezone, see http://php.net/manual/en/timezones.php
  • created, timestamp on when the user account was created
  • changed, timestamp on when the user account was changed
  • access, timestamp on when the user last accessed the site
  • login, timestamp on when the user last logged in
  • init, the initial email address used when the user account was created 

Other source plugins

The examples on this page use the embedded_data source plugin for the sake of simplicity so that this example can be copy-pasted as a working example. In the real world, you would most probably want to migrate the nodes using for example the CSV source plugin or to write a simple SQL source plugin to read the source data from another database.

Executing the migrations

Read more on how to execute migrations.

Help improve this page

Page status: No known problems

You can: