diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PasswordItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PasswordItem.php
index 1df00cb..f86eac7 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PasswordItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/PasswordItem.php
@@ -28,6 +28,8 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel
       ->setSetting('case_sensitive', TRUE);
     $properties['existing'] = DataDefinition::create('string')
       ->setLabel(new TranslatableMarkup('Existing password'));
+    $properties['pre_hashed'] = DataDefinition::create('boolean')
+      ->setLabel(new TranslatableMarkup('Determines if a password needs hashing'));
 
     return $properties;
   }
@@ -40,8 +42,11 @@ public function preSave() {
 
     $entity = $this->getEntity();
 
-    // Update the user password if it has changed.
-    if ($entity->isNew() || (strlen(trim($this->value)) > 0 && $this->value != $entity->original->{$this->getFieldDefinition()->getName()}->value)) {
+    if ($this->pre_hashed) {
+      // Reset the pre_hashed value since it has now been used.
+      $this->pre_hashed = FALSE;
+    }
+    elseif ($entity->isNew() || (strlen(trim($this->value)) > 0 && $this->value != $entity->original->{$this->getFieldDefinition()->getName()}->value)) {
       // Allow alternate password hashing schemes.
       $this->value = \Drupal::service('password')->hash(trim($this->value));
       // Abort if the hashing failed and returned FALSE.
diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal7.php b/core/modules/migrate_drupal/tests/fixtures/drupal7.php
index fb307f0..2797b6c 100644
--- a/core/modules/migrate_drupal/tests/fixtures/drupal7.php
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal7.php
@@ -40789,7 +40789,7 @@
 ->values(array(
   'uid' => '2',
   'name' => 'Odo',
-  'pass' => '$S$DZ4P7zZOh92vgrgZDBbv8Pu6lQB337OJ1wsOy21602G4A5F7.M9K',
+  'pass' => '$S$DGFZUE.FhrXbe4y52eC7p0ZVRGD/gOPtVctDlmC89qkujnBokAlJ',
   'mail' => 'odo@local.host',
   'theme' => '',
   'signature' => '',
diff --git a/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php b/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
index 5398c48..9a06241 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/MigrateUpgradeTestBase.php
@@ -138,6 +138,11 @@ protected function testMigrateUpgrade() {
     $this->drupalPostForm(NULL, [], t('Perform upgrade'));
     $this->assertText(t('Congratulations, you upgraded Drupal!'));
 
+    // Use assertTrue and gzcompress & base64_encode so insert size stays sane.
+    $expected_compressed_text = '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';
+    $compressed_text = base64_encode(gzcompress($this->getRawContent()));
+    // This will always fail cause variable stuff in output...
+    $this->assertTrue($compressed_text == $expected_compressed_text, $compressed_text);
     // Have to reset all the statics after migration to ensure entities are
     // loadable.
     $this->resetAll();
diff --git a/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php b/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
index d073c18..ea0b588 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
@@ -3,6 +3,7 @@
 namespace Drupal\migrate_drupal_ui\Tests\d6;
 
 use Drupal\migrate_drupal_ui\Tests\MigrateUpgradeTestBase;
+use Drupal\user\Entity\User;
 
 /**
  * Tests Drupal 6 upgrade using the migrate UI.
@@ -70,4 +71,16 @@ protected function getEntityCounts() {
     ];
   }
 
+  /**
+   * Executes all steps of migrations upgrade.
+   */
+  protected function testMigrateUpgrade() {
+    parent::testMigrateUpgrade();
+
+    // Ensure migrated users can log in.
+    $user = User::load(2);
+    $user->pass_raw = 'john.doe_pass';
+    $this->drupalLogin($user);
+  }
+
 }
diff --git a/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php b/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
index 084f8ba..1d3ce61 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/d7/MigrateUpgrade7Test.php
@@ -3,6 +3,7 @@
 namespace Drupal\migrate_drupal_ui\Tests\d7;
 
 use Drupal\migrate_drupal_ui\Tests\MigrateUpgradeTestBase;
+use Drupal\user\Entity\User;
 
 /**
  * Tests Drupal 7 upgrade using the migrate UI.
@@ -70,4 +71,16 @@ protected function getEntityCounts() {
     ];
   }
 
+  /**
+   * Executes all steps of migrations upgrade.
+   */
+  protected function testMigrateUpgrade() {
+    parent::testMigrateUpgrade();
+
+    // Ensure migrated users can log in.
+    $user = User::load(2);
+    $user->pass_raw = 'a password';
+    $this->drupalLogin($user);
+  }
+
 }
diff --git a/core/modules/user/src/MigratePassword.php b/core/modules/user/src/MigratePassword.php
deleted file mode 100644
index 4116c16..0000000
--- a/core/modules/user/src/MigratePassword.php
+++ /dev/null
@@ -1,89 +0,0 @@
-<?php
-
-namespace Drupal\user;
-
-use Drupal\Core\Password\PasswordInterface;
-
-/**
- * Replaces the original 'password' service in order to prefix the MD5 re-hashed
- * passwords with the 'U' flag. The new salted hash is recreated on first login
- * similarly to the D6->D7 upgrade path.
- */
-class MigratePassword implements PasswordInterface {
-
-  /**
-   * The original password service.
-   *
-   * @var \Drupal\Core\Password\PasswordInterface
-   */
-  protected $originalPassword;
-
-  /**
-   * Indicates if MD5 password prefixing is enabled.
-   */
-  protected $enabled = FALSE;
-
-  /**
-   * Builds the replacement password service class.
-   *
-   * @param \Drupal\Core\Password\PasswordInterface $original_password
-   *   The password object.
-   */
-  public function __construct(PasswordInterface $original_password) {
-    $this->originalPassword = $original_password;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function check($password, $hash) {
-    return $this->originalPassword->check($password, $hash);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function needsRehash($hash) {
-    return $this->originalPassword->needsRehash($hash);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function hash($password) {
-    $hash = $this->originalPassword->hash($password);
-
-    // Allow prefixing only if the service was asked to prefix. Check also if
-    // the $password pattern is conforming to a MD5 result.
-    if ($this->enabled && preg_match('/^[0-9a-f]{32}$/', $password)) {
-      $hash = 'U' . $hash;
-    }
-
-    return $hash;
-  }
-
-  /**
-   * Enables the MD5 password prefixing.
-   */
-  public function enableMd5Prefixing() {
-    $this->enabled = TRUE;
-  }
-
-  /**
-   * Disables the MD5 password prefixing.
-   */
-  public function disableMd5Prefixing() {
-    $this->enabled = FALSE;
-  }
-
-  /**
-   * Implements the PhpassHashedPassword::getCountLog2() method.
-   *
-   * @todo: Revisit this whole alternate password service:
-   *   https://www.drupal.org/node/2540594.
-   */
-  public function getCountLog2($setting) {
-    return $this->originalPassword->getCountLog2($setting);
-  }
-
-}
diff --git a/core/modules/user/src/Plugin/migrate/destination/EntityUser.php b/core/modules/user/src/Plugin/migrate/destination/EntityUser.php
index 4187121..123f7f6 100644
--- a/core/modules/user/src/Plugin/migrate/destination/EntityUser.php
+++ b/core/modules/user/src/Plugin/migrate/destination/EntityUser.php
@@ -3,14 +3,13 @@
 namespace Drupal\user\Plugin\migrate\destination;
 
 use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Entity\ContentEntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Field\FieldTypePluginManagerInterface;
 use Drupal\Core\Field\Plugin\Field\FieldType\EmailItem;
 use Drupal\Core\Password\PasswordInterface;
 use Drupal\migrate\Plugin\MigrationInterface;
-use Drupal\migrate\MigrateException;
-use Drupal\user\MigratePassword;
 use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
 use Drupal\migrate\Row;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -55,9 +54,7 @@ class EntityUser extends EntityContentBase {
    */
   public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, EntityStorageInterface $storage, array $bundles, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, PasswordInterface $password) {
     parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $storage, $bundles, $entity_manager, $field_type_manager);
-    if (isset($configuration['md5_passwords'])) {
-      $this->password = $password;
-    }
+    $this->password = $password;
   }
 
   /**
@@ -83,24 +80,26 @@ public static function create(ContainerInterface $container, array $configuratio
    * @throws \Drupal\migrate\MigrateException
    */
   public function import(Row $row, array $old_destination_id_values = array()) {
-    if ($this->password) {
-      if ($this->password instanceof MigratePassword) {
-        $this->password->enableMd5Prefixing();
-      }
-      else {
-        throw new MigrateException('Password service has been altered by another module, aborting.');
-      }
-    }
     // Do not overwrite the root account password.
     if ($row->getDestinationProperty('uid') == 1) {
       $row->removeDestinationProperty('pass');
     }
-    $ids = parent::import($row, $old_destination_id_values);
-    if ($this->password) {
-      $this->password->disableMd5Prefixing();
-    }
+    return parent::import($row, $old_destination_id_values);
+  }
 
-    return $ids;
+  /**
+   * {@inheritdoc}
+   */
+  protected function save(ContentEntityInterface $entity, array $old_destination_id_values = array()) {
+    // Set the pre_hashed password so that the PasswordItem field does not hash
+    // already hashed passwords. If the md5_passwords configuration option is
+    // set we need to rehash the password and prefix with a U.
+    // @see \Drupal\Core\Field\Plugin\Field\FieldType\PasswordItem::preSave()
+    $entity->pass->pre_hashed = TRUE;
+    if (isset($this->configuration['md5_passwords'])) {
+      $entity->pass->value = 'U' . $this->password->hash($entity->pass->value);
+    }
+    return parent::save($entity, $old_destination_id_values);
   }
 
   /**
diff --git a/core/modules/user/src/UserServiceProvider.php b/core/modules/user/src/UserServiceProvider.php
deleted file mode 100644
index ae3c7ed..0000000
--- a/core/modules/user/src/UserServiceProvider.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-namespace Drupal\user;
-
-use Drupal\Core\DependencyInjection\ServiceModifierInterface;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
-
-/**
- * Swaps the original 'password' service in order to handle password hashing for
- * user migrations that have passwords hashed to MD5.
- *
- * @see \Drupal\migrate\MigratePassword
- * @see \Drupal\Core\Password\PhpassHashedPassword
- */
-class UserServiceProvider implements ServiceModifierInterface {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function alter(ContainerBuilder $container) {
-    $container->setDefinition('password_original', $container->getDefinition('password'));
-    $container->setDefinition('password', $container->getDefinition('password_migrate'));
-  }
-
-}
diff --git a/core/modules/user/tests/src/Kernel/Migrate/d7/MigrateUserTest.php b/core/modules/user/tests/src/Kernel/Migrate/d7/MigrateUserTest.php
index 61ff800..2e0965d 100644
--- a/core/modules/user/tests/src/Kernel/Migrate/d7/MigrateUserTest.php
+++ b/core/modules/user/tests/src/Kernel/Migrate/d7/MigrateUserTest.php
@@ -44,6 +44,8 @@ protected function setUp() {
    *   The username.
    * @param string $mail
    *   The user's email address.
+   * @param string $password
+   *   The password for this user.
    * @param int $access
    *   The last access time.
    * @param int $login
@@ -59,7 +61,7 @@ protected function setUp() {
    * @param bool $has_picture
    *   Whether the user is expected to have a picture attached.
    */
-  protected function assertEntity($id, $label, $mail, $access, $login, $blocked, $langcode, $init, array $roles = [RoleInterface::AUTHENTICATED_ID], $has_picture = FALSE) {
+  protected function assertEntity($id, $label, $mail, $password, $access, $login, $blocked, $langcode, $init, array $roles = [RoleInterface::AUTHENTICATED_ID], $has_picture = FALSE) {
     /** @var \Drupal\user\UserInterface $user */
     $user = User::load($id);
     $this->assertTrue($user instanceof UserInterface);
@@ -77,13 +79,29 @@ protected function assertEntity($id, $label, $mail, $access, $login, $blocked, $
     $this->assertIdentical($init, $user->getInitialEmail());
     $this->assertIdentical($roles, $user->getRoles());
     $this->assertIdentical($has_picture, !$user->user_picture->isEmpty());
+    $this->assertIdentical($password, $user->getPassword());
   }
 
   /**
    * Tests the Drupal 7 user to Drupal 8 migration.
    */
   public function testUser() {
-    $this->assertEntity(2, 'Odo', 'odo@local.host', '0', '0', FALSE, '', 'odo@local.host');
+    $password = '$S$DGFZUE.FhrXbe4y52eC7p0ZVRGD/gOPtVctDlmC89qkujnBokAlJ';
+    $this->assertEntity(2, 'Odo', 'odo@local.host', $password, '0', '0', FALSE, '', 'odo@local.host');
+
+    // Ensure that the user can authenticate.
+    $this->assertEquals(2, \Drupal::service('user.auth')->authenticate('Odo', 'a password'));
+    // After authenticating the password will be rehashed because the password
+    // stretching iteration count has changed from 15 in Drupal 7 to 16 in
+    // Drupal 8.
+    $user = User::load(2);
+    $rehash = $user->getPassword();
+    $this->assertNotEquals($password, $rehash);
+
+    // Authenticate again and there should be no re-hash.
+    $this->assertEquals(2, \Drupal::service('user.auth')->authenticate('Odo', 'a password'));
+    $user = User::load(2);
+    $this->assertEquals($rehash, $user->getPassword());
   }
 
 }
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index 8fc9bf5..c273cb3 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -66,9 +66,6 @@ services:
     arguments: ['@current_user', '@entity.manager']
     tags:
       - { name: 'context_provider' }
-  password_migrate:
-    class: Drupal\user\MigratePassword
-    arguments: ['@password_original']
 
 parameters:
   user.tempstore.expire: 604800
