Change record status: 
Project: 
Introduced in branch: 
10.1.x
Introduced in version: 
10.1.0
Description: 

Drupal uses the PHP password_hash() and password_verify() functions to store and verify passwords.

The previous algorithm is in the new Password Compatibility module. It is installed when updating or upgrading. But, keeping the module installed defeats the security hardening provided by the new algorithm. See the section below, "When to uninstall Password Compatibility".

Updating

When a site updates to Drupal 10.1.0 or later, a database-update function installs the Password Compatibility module. This allows existing users to use their credentials. If the module is not installed, existing users can login by requesting a new password.

The first time an existing user logs in, a new hash is and saved to the database. From then on, the user can log in with the same credentials whether this module is installed or not.

Users who login with some other method, such as a one-time login link, and do not update their passwords, will not have the new hash.

Upgrading from Drupal 6 or Drupal 7

The Migrate Drupal module declares a dependency on the Password Compatibility module. As a result, it is installed when Migrate Drupal is installed.

If you can not log in

  1. Log in as a site administrator using a one-time login link.
  2. Enable the phpass module using Drush.
  3. Set $settings['update_free_access'] = TRUE; in settings.php and then visit https://mysite.com/update.php.

When to uninstall Password Compatibility

Sites may choose when to uninstall the Password Compatibility module. For example, after the majority of users have logged in at least once. Below are two methods to find the users that are using the legacy hash.

  1. A site administrator can visit /admin/people and sort by "Last access". Any user who has logged in with username and password since the upgrade to Drupal 10.1.0 should have an updated password hash.
  2. The most reliable way to find legacy password hashes is with a database query. The new hashes all start with $2y$. Use the following query to find user accounts that have the legacy hash.

    SELECT uid, name, mail FROM users_field_data WHERE pass IS NOT NULL AND pass NOT LIKE '$2y$%';

API changes

  1. There is a new password service, Drupal\Core\Password\PhpPassword. It wraps password_hash(), password_verify() and password_needs_rehash().
  2. The implementation of Drupal\Core\Password\PhpassHashedPassword is moved to a new phpass module.
  3. A deprecated subclass is left at Drupal\Core\Password\PhpassHashedPassword and removed in Drupal 11.0
Impacts: 
Site builders, administrators, editors
Module developers

Comments

ressa’s picture

Thanks for this improvement. I created #3380421: Mention on project page phpass is in Drupal core since 10.1, since I found that project after searching for more info after seeing configuration changes after an update.

andypost’s picture

A cost of 12 is well below 0.5 seconds on all tested CPUs (with the slowest CPU being at 330ms) and should feel sufficiently snappy for an interactive login in a website even when needing to rehash a cost 10 hash during login.

The RFC commited to PHP 8.4 https://github.com/php/php-src/pull/12367

codebymikey’s picture

You may check for legacy hashes in Drush using:

drush sql:query "SELECT uid, name, mail FROM users_field_data WHERE pass IS NOT NULL AND pass NOT LIKE '$2y$%'"