Problem:
When users reset their password as anon with simple_pass_reset and "force password change" is checked on that user, password_policy makes them reset their password a second time after login.

When saving a user, password_policy does this:

  global $user;

  // If the current user is being forced to change their password and is
  // changing their password, toggle the force_change field off.
  if (isset($account->original->force_password_change) && $account->original->force_password_change && isset($edit['pass']) && $user->uid == $account->uid) {
    db_update('password_policy_force_change')
      ->fields(array(
        'force_change' => 0,
      ))
      ->condition('uid', $account->uid)
      ->execute();

However, when a user account is being saved by simple_pass_reset this fails because when users are setting their password via the simple_pass_reset module they are not logged in and thus $user->uid is zero and does not match $user->account uid.

I solved this with a custom module:

function mymodule_user_update(&$edit, $account, $category) {
  // This code is exactly like `password_policy_user_update` except they check
  // that $user->uid == $account->uid. But when allowing password reset before login
  // using simple_pass_reset, $user->uid is 0--but a legitimate password update
  // is being performed. So this additional safety check can be bypassed.
  global $user;
  if (isset($account->original->force_password_change)
    && $account->original->force_password_change
    && isset($edit['pass'])
    && $user->uid == 0) {
    db_update('password_policy_force_change')
      ->fields(array(
        'force_change' => 0,
      ))
      ->condition('uid', $account->uid)
      ->execute();
    db_delete('password_policy_expiration')
      ->condition('uid', $account->uid)
      ->execute();
  }
}

I imagine dev is mostly happening on D8, but I wanted to post for others in case this was happening to them and they wanted to use this workaround.

Comments

glass.dimly created an issue. See original summary.

aohrvetpv’s picture

Does this work?

I think the && $user->uid == $account->uid condition that is causing the problem with Simple Password Reset may be unnecessary. All tests pass without the condition, so either Password Policy test coverage is incomplete, or the condition is unnecessary. Looking at Git history and drupal.org issues, I don't understand its purpose.

aohrvetpv’s picture

Status: Active » Needs review

  • AohRveTPV committed 83db3d4 on 7.x-1.x
    Issue #3033387 by AohRveTPV: Forces user password reset after password...
aohrvetpv’s picture

Status: Needs review » Fixed

Was able to reproduce it (I think) and the patch in #2 seems to fix.

Steps to reproduce:
1. Set "Force password change" for a user 'foo'.
2. Request new password for 'foo'.
3. Use link in email to change password.

Before patch:
After changing password once, user is prompted to change password a second time.

After patch:
User is only prompted to change password once.

Thanks, glass.dimly, for reporting the problem and isolating its cause. Please re-open the issue if the commit doesn't actually fix the problem.

aohrvetpv’s picture

Status: Fixed » Needs review
StatusFileSize
new985 bytes

Need to update comment, per logic change, to remove word "current".

aohrvetpv’s picture

Title: Forces user password reset after password was reset already by simple_pass_reset » Forces user password reset after password was reset already by simple_pass_reset

Status: Needs review » Needs work

  • AohRveTPV committed a563975 on 7.x-1.x
    Revert "Issue #3033387 by AohRveTPV: Forces user password reset after...
aohrvetpv’s picture

Status: Needs work » Needs review

  • AohRveTPV committed 8ad7e55 on 7.x-1.x
    Issue #3033387 by AohRveTPV: Forces user password reset after password...
aohrvetpv’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.