Password policy keeps on telling "Your password has expired, please update it", even if the password is changed.

Created on 3 February 2021, almost 4 years ago
Updated 10 September 2024, 2 months ago

Password policy keeps on telling "Your password has expired, please update it", even if the password is changed.

Steps to reproduce

Create user with content manager role and then reset password. Next time when user will login will get into infinite loop of password reset.

๐Ÿ› Bug report
Status

Postponed: needs info

Version

4.0

Component

Code

Created by

๐Ÿ‡ฎ๐Ÿ‡ณIndia Deepika Dhiman

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • First commit to issue fork.
  • Open on Drupal.org โ†’
    Core: 10.0.7 + Environment: PHP 7.4 & MySQL 5.7
    last update over 1 year ago
    Waiting for branch to pass
  • Status changed to Needs review over 1 year ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States briantschu

    If a user doesn't have the permission 'manage password reset', then the code is setting #access to the 3 password policy fields on the user edit form to false.

    During validation, the code will still update these fields (even though #access is false), but the values aren't saved because the user doesn't have access to the fields. The field that needs to be updated, but isn't, is `field_password_expiration`. Since this value isn't getting re-set to '0' when the user changes their password, they're getting stuck in a password reset loop.

    The only approach that I found that works is changing the 3 fields to be hidden fields, rather than setting #access to false. This allows the fields to be hidden from the user, but still get updated when the user saves the form with their updated password.

    I tried a few different approaches to fixing this, including using setValueForElement in the _password_policy_user_profile_form_update_fields validation method, but that didn't seem to work.

  • Hello @briantschu,

    Upon applying this update I recieved the following error:

    TypeError: Cannot access offset of type string on string in _password_policy_user_profile_form_validate() (line 207 of modules/contrib/password_policy/password_policy.module).

    _password_policy_user_profile_form_validate(Array, Object)
    call_user_func_array('_password_policy_user_profile_form_validate', Array) (Line: 82)
    Drupal\Core\Form\FormValidator->executeValidateHandlers(Array, Object) (Line: 275)
    Drupal\Core\Form\FormValidator->doValidateForm(Array, Object, 'user_form') (Line: 118)
    Drupal\Core\Form\FormValidator->validateForm('user_form', Array, Object) (Line: 593)
    Drupal\Core\Form\FormBuilder->processForm('user_form', Array, Object) (Line: 325)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
    Drupal\Core\Controller\FormController->getContentResult(Object, Object)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 169)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 50)
    Drupal\ban\BanMiddleware->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
    Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 718)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

    Would you be able to provide any additional insight here?

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States briantschu

    @cjsingle, can you confirm that you're using version 4.0.0 of the module? When I look at line 207 of the password_policy.module file, it's a comment.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States mpotter

    Wondering if this is the cause of the problem on our site. We only have a few users, but on two occasions, when a non-admin user has had their password expire, they were not able to change it and kept getting login errors, eventually causing them to get added to the flood control table. We don't have email allowed on this server so they are not able to send a password reset link.

    So would like some feedback on whether the patch presented above is the correct approach? If so, then I can try to reproduce the issue and see if this fixes it.

    My worry about just setting the fields to hidden is that someone could hack the form to change these values when they don't have the permission. In which case it basically makes that permission invalid.

  • ๐Ÿ‡ธ๐Ÿ‡ฎSlovenia useernamee Ljubljana

    I'm experiencing this issue as well on version 4.0.0 of the password_policy module.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia ankithashetty Karnataka, India

    +1 to this issue.

  • ๐Ÿ‡ธ๐Ÿ‡ฎSlovenia useernamee Ljubljana

    This patch did not fix the issue for me.

  • ๐Ÿ‡ธ๐Ÿ‡ฎSlovenia useernamee Ljubljana

    After investigation the field_last_password_reset is not set to new value on user.

    In function _password_policy_user_profile_form_update_fields in password_policy.module it is set on $form_state object, but this is then not changed on the user entity:

      // Update if both current and new password fields are filled out. Depending
      // on policy settings, user may be allowed to use same password again.
      if ($uid && ($current_pass || $form_state->get('user_pass_reset')) && $new_pass) {
        $date = \Drupal::service('date.formatter')->format(\Drupal::time()->getRequestTime(), 'custom', DateTimeItemInterface::DATETIME_STORAGE_FORMAT, DateTimeItemInterface::STORAGE_TIMEZONE);
        $form_state->setValue(
          'field_last_password_reset',
          [['value' => $date]]
        );
        $form_state->setValue('field_password_expiration', ['value' => '0']);
        $form_state->setValue('field_pending_expire_sent', ['value' => '0']);
      }
    
  • Status changed to RTBC 12 months ago
  • ๐Ÿ‡ธ๐Ÿ‡ฎSlovenia useernamee Ljubljana
  • Assigned to Kristen Pol
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States Kristen Pol Santa Cruz, CA, USA

    Assigning to myself as I'm reviewing/merging ready RTBC fixes/updates over the next few days.

  • Issue was unassigned.
  • Status changed to Postponed: needs info 9 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States Kristen Pol Santa Cruz, CA, USA

    I've tested on 10.1.8 with Umami profile and don't have a problem when using a non-admin account. Please provide detailed steps to reproduce including the version number.

    Also, I'm not sure I agree with the approach either as in #13 but I can review further once I can reproduce.

  • Status changed to Closed: works as designed 7 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States Kristen Pol Santa Cruz, CA, USA

    Given there has been no follow up on this, I'm closing this. If you are still experiencing this issue, please add concrete steps to reproduce in the summary.

  • Status changed to Active 6 months ago
  • ๐Ÿ‡ฏ๐Ÿ‡ดJordan Ahmad Khader

    the issue is that the administrator doesn't enter _password_policy_user_profile_form_update_fields validation which resets the expiration password.

  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom billy.davies

    billy.davies โ†’ made their first commit to this issueโ€™s fork.

  • Pipeline finished with Failed
    5 months ago
    Total: 415s
    #209563
  • ๐Ÿ‡ฌ๐Ÿ‡งUnited Kingdom billy.davies

    Steps to reproduce as follows:

    1. Install the module and create a password policy.
    2. Modify the User Profile form display settings (via /admin/config/people/accounts/form-display) to include the "Password Expiration" field.
    3. Create a user role that does not have the "Manage password reset" permission.
    4. Create a new user with the role you just created.
    5. Use the "Force Password Reset" functionality (via /admin/config/security/password-policy/reset) to expire the passwords of all users with the new role.
    6. Login as the new user you created and you are directed to reset your password.
    7. Reset your password following the password policy rules. This will show a confirmation message that the password was successfully updated.
    8. Browse to any page (or refresh the current page) and you will be sent back to the "Your password has expired" workflow.

    As identified in #10 this is because the password reset related fields are present in the edit user form but the user without the "Manage password reset" permission does not have permission to use them. Merge request https://git.drupalcode.org/project/password_policy/-/merge_requests/58 works around this by hiding the fields, but as identified in #13 users could manipulate the fields when they shouldn't be able to. I've created a merge request that removes the fields from the form if a user doesn't have the "Manage password reset" permission to resolve the issue whilst maintaining security.

  • First commit to issue fork.
  • Status changed to Needs review 2 months ago
  • ๐Ÿ‡บ๐Ÿ‡ฆUkraine rollins
  • Status changed to Postponed: needs info 2 months ago
  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia vishalkhode

    Not able to reproduce the issue with latest release. Followed the steps as mentioned in #25 and also followed the steps that's added in the ticket. Feel free to re-open the ticket, if this issue still occurs and we've the steps to reproduce the issue.
    Thanks.

Production build 0.71.5 2024