Hi,
I am using the Password Reset Landing Page (PRLP) along with the password policy module.
The Password Reset Landing Page (PRLP) is a small module that basically makes users reset their passwords straight from the reset screen.
The password policy does not work with it but the changes that it would need to make it support it would be minor.
At this moment, because I don't really wanna change the Password Policy core module I am using hook_form_alter like this:
function mymodule_form_alter(&$form, $form_state, $form_id) {
global $user;
if (!in_array($form_id, array('user_pass_reset'))) {
return;
}
password_policy_password_element_alter($form['account']['pass'], $user);
$form['#validate'][] = 'password_policy_user_profile_form_validate';
$form['#submit'][] = 'password_policy_password_submit';
}
For Password Policy to support this module the changes would be basically:
1) Replace the $form['#user'] used in password_policy_form_alter to something like a global $user variable. This because the user is anonymous in password reset screen so that form variable isn't available, but the $user variable is.
2) Add the reset_form id to the in_array check being done in the beginning of password_policy_form_alter making it work on the reset pass form.
Will supply in next post a patch to the password policy module that would apply these changes.
Would be awesome to have this support in Password Policy module.
Thanks in advance and I hope this helps someone out!
Comments
Comment #1
kyuubi commentedAs promised here is the patch.
Comment #2
aohrvetpv commentedThis will be a good feature to add. The patch is straightforward but I think it is problematic. It is module-specific integration code which--as with all module-specific integration code--increases the complexity of the module and will make it harder to ensure it is fully working.
If someone reads the code for the first time, they will wonder "Why are we modifying the password field on the
user_pass_resetform when there is no password field on that form?" We could add a comment to explain that it is for PRLP, or they could figure it out through the Git log, etc., but this is still adding a special case which increases the complexity of the code.Over time, how will we know this code still works for the
user_pass_resetform, unless we have an automated test that tests the integration with the PRLP module?I think a better approach might be a general one that checks all forms for the presence of the user password fields and always customizes them, instead of hard-coding all the specific form IDs where they might possibly appear. I am not sure if it can be done robustly or performantly.
Comment #3
tancMuch like kyuubi's hook_form_alter, here's how we integrated the two on one project:
Putting the code here in case it helps anyone coming across this issue.
Comment #4
kyuubi commentedHi guys,
Thanks for your replies.
AohRveTPV, I do understand your arguments and you've got a solid point.
I think though, that checking the presence of fields adds even more complexity than an additional key but I also understand the need to avoid assumptions that are not core.
One solution that could be beneficial would be a simple UI where the user can add himself additional form keys to be checked.
This way there is no assumption to a specific module approach but the flexibility to support additional forms, wherever they may be.
What do you think?
Comment #5
aohrvetpv commentedThis is a possibility but I think it would be better if the modules just worked together without any manual configuration by the administrator.
Attached is a patch that removes the hard-coding of form IDs. A sufficient check for the password field seems to be just:
It is more complex than the original code though because it was necessary to force the
hook_form_alter()to execute after thehook_form_FORM_ID_alter()of Password Reset Landing Page usinghook_module_implements_alter(). Otherwise Password Policy does not get the password field in the$formobject, because PRLP useshook_form_FORM_ID_alter()to inject it. The patch in #1 does not seem to work due to this call ordering, and I think the excerpt in #3 only works if the module is properly weighted or you get lucky. Please correct me if wrong.The JavaScript constraint checking does not fully work with this patch, because
$useris the anonymous user inpassword_policy_ajax_check()instead of the user for whom the password is being changed. (This is also a problem with the patch in #1 and the excerpt in #3). For instance, if only the username constraint is enabled, and user 'foo' tries to set their password to 'foo', the JavaScript check will tell the user that all constraints are satisfied, but when they submit, validation will fail.Comment #6
aohrvetpv commentedComment #7
stephen-cox commentedThis is my patch for this issue with the 7.x-1.dev release. I'll look at testing patch #5 with 7.x-2.dev when I get a chance.
Comment #8
dydave commentedSwitching issue status to Needs review for review, testing and reporting of latest patch (see #7).
It would be great if Automated Testing could be enabled in module's tracker.
Cheers!
Comment #10
dydave commentedCorrection on previous comment: Automated Testing is enabled. This issue just never got in Needs review status.
Forgot to relate it with Password Reset Landing Page (PRLP)'s #2294381: No minimal password length?, thus another edit.
Cheers!
Comment #12
aohrvetpv commentedThanks for the 7.x-1.x patch in #7, but it has the same problem as mentioned in #2. Maybe #5 could be backported.
The automated tests have probably failed for #7 because the version of this issue is currently set to 7.x-2.x-dev. New features should go in to 2.x first (per project page).
Comment #13
aohrvetpv commentedOne solution to this would be to pass the user ID as a POST parameter, so
password_policy_ajax_check()can load the appropriate user object. This would introduce a security flaw, though, because if the history constraint were enabled, AJAX requests could then be used to brute force previous user passwords for arbitrary users.Comment #14
stephen-cox commentedA possible way to the prevent brute force attacks, or at least slow them down, would be to use Drupal's flood control. Every time
password_policy_ajax_check()is called an event is registered withflood_register_event()[1] and then a check is made to see if there have been too many connection attempts withflood_is_allowed()[2].I'm happy to look into putting a patch together for this if it is thought to be a good solution.
[1] https://api.drupal.org/api/drupal/includes!common.inc/function/flood_register_event/7
[2] https://api.drupal.org/api/drupal/includes!common.inc/function/flood_is_allowed/7
Comment #15
rakesh.nimje84@gmail.com commented#7 works in my case for 7.x-1.x
Thanks stephen-cox for your efforts.
Comment #16
Stefan97 commentedHi,
I have the exact same problem, but after reading all this I still don't know how to solve it.
Anyone can help me please?
Comment #17
aohrvetpv commentedStefan97, I do not think there is a fully working solution for 7.x-2.x currently. The 7.x-2.x patch in #5 seems to have problems. The 7.x-1.x patch in #7 may work, though.
Edit: Updating this comment as I misread the patch in #7 before. It looks to not have the problem I thought it did.
Comment #18
aohrvetpv commentedI have the objections in #2 to patch in #7: We should not be hard-coding
user_pass_resetin the code because it will not be clear to someone reading the code why that is there, and it would not be covered by tests. A better approach would seem to be to check for the presence of the password fields and modify those forms. If the password and confirm password fields are present, you know it is a form on which the password can be changed.Comment #19
nancydruHow about if the code in password_policy_form_alter() were placed into a callable function so that other modules could call it?How about:
Comment #20
aohrvetpv commentedIn my opinion, the proper solution would be for PRLP and Password Policy to work together without knowing about each other. The suggestion in #19 is good, but would require PRLP to know about Password Policy (i.e., have code in its module specifically to integrate with Password Policy).
Comment #21
oleksiyAgree with @NancyDru. It will be useful. Have provided patch for it https://www.drupal.org/node/2562481
Comment #22
pradeep22saini commentedUsing patch #5
On applying this patch.
with 7.2.x branch.
Call to undefined function password_policy_password_submit();
Need to remove this and it's working fine.
Comment #23
Anonymous (not verified) commentedAt this time the Dev version of password policy actually makes things worse. At least when the 1 time email link is used with the prod version of password policy it will show you what requirements (alpha, at least 1 symbol, >7 etc) are needed. But the dev version now (when using 1 time email link) doesn't even show that, it just shows the standard drupal message of make it at least 6, use upper / lower case etc.
Not sure if its #21 that set us back. Perhaps if #22 is implemented and it can get tested then this issue can be resolved. For now the issue here https://www.drupal.org/node/2294381 is still a problem.
I'm sorry I don't know code well enough to solve this once and for all.
Comment #24
aohrvetpv commentedJust tried PRLP with the latest 7.x-2.x release (7.x-2.0-alpha6), and policies seem to be applied to the password field at
user/%uid/editupon login.emag, could you post which Password Policy version number you are experiencing the problem with? Did you change any of the default PRLP settings?
Comment #25
Anonymous (not verified) commentedI'm using password policy 7.x-2.0-alpha6 (used the default and enabled it) and prlp 7.x-.1.1 (used defaults). Disabled logintoboggan as well.
Let me clarify my steps:
1. Went to account page (for a non admin user), edit, and clicked "request new password"
2. Clicked "email new password". Then logged out.
3. Went to email and clicked the one time use link.
4. Am brought to the user/reset/uid url. The "to make password stronger:" shows make it at least 6, add lowercase, add upper, add numbers, add punctuation. I entered 1 character , an "m" in the password and confirm password field.
5. I then logged out.
6. I then used the username and the password of "m" and it worked.
Note: the 'default' password policy requires min of 8 char and at least 1 symbol one letter etc. On step 4 I wasn't given that info. When I am on the user/uid/edit screen the "passwords must meet the following requirements" does show the 'default' settings of 1 letter, 8 char, 1 digit etc.
The issue is when on the prlp password change screen from a 1-time-email the password policy settings aren't enforced.
Hope that helps, if you need more info I'll do the best I can to help.
Comment #26
aohrvetpv commentedComment #27
aohrvetpv commentedemag, thanks, I was able to reproduce the problem following your steps in #25 on a fresh Drupal site.
The cause of the problem is that Password Policy checks for the password element in
hook_form_alter(), and modifies it as necessary. However, PRLP adds the password element to theuser_reset_formusinghook_form_FORM_ID_alter(), which is called afterhook_form_alter(). So Password Policy does not see the added password element.Per https://api.drupal.org/api/drupal/modules!system!system.api.php/function... :
I am not sure of a good solution to this problem. Any suggestions? I would not want Password Policy to have any specific knowledge of PRLP (i.e., no "if PRLP..." logic).
Comment #28
aohrvetpv commentedPosted PRLP patch which seems to fix the incompatibility with latest Password Policy 7.x-2.x, in this comment:
#2294381-5: No minimal password length?
If either module is going to have knowledge of the other, it may make more sense for PRLP to know about Password Policy, than vice versa, since PRLP is (currently) the less popular module (in terms of site installations).
Comment #29
Anonymous (not verified) commentedThe patch works. Thank you for such a quick response!! I noticed two other issues: first is listed below, the second I opened a new issue.
Picking up from my prior steps...
3. Went to email and clicked the one time use link.
4. Am brought to the user/reset/uid url. I'm forced to change the password in compliance with password policy. AWESOME!
5. I'm brought to the user/uid/edit screen. The first two messages are fine: 'you have successfully validated your email address' and 'your new password has been saved'. HOWEVER, the third message says 'you have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'
The last sentence: "Please change your password." shouldn't be there since the user has already changed it in the prior PRLP screen.
Would be nice if that could get cleaned up. Let me know if this is an issue with PRLP and I could open the issue there if needed.
Comment #30
Anonymous (not verified) commentedThe second issue wasn't an issue so no new one opened.
Comment #31
aohrvetpv commentedCannot reproduce this. I followed steps 3 and 4, and am redirected to the
user/%uid/editpage, but no messages are displayed.I am using a fresh Drupal site. I just enabled the default, example password policy and left PRLP set to its defaults. Maybe you could try reproducing this problem from a fresh Drupal site? Perhaps there is something else involved here.
Comment #32
royerd commentedCould someone clarify for me . . . ? It sounds like one of the solutions listed above works, but I'm not clear which one. Is the fix now in the Dev version of this module? It also sounds like one also needs to be using the Dev version of PRLP as well.
Comment #33
royerd commentedI answered my own question by installing Dev on both this and the PRLP module. The policy compliance is now enforced using PRLP. There still remains the java script issue described in #15 but at least the module works otherwise. Thanks for everyone's work on this issue.
Comment #34
andypostthere's a patch, so should be NW or NR
Comment #35
abaier commentedWas this issue only fixed for the 7.x-2 branch? I am using the latest password_policy 7.x-1.x-dev from today with PRLP 7.x-1.13, where the patch from #28 should be commited. Unfortunately on the password reset page Drupal's default password hints are shown instead of my password policy settings and it is even possible to submit the form with a one-digit-password …
Thanks for a quick reply!
Comment #36
aohrvetpv commentedABaier, I am guessing the problem with PRLP and Password Policy 7.x-1.x is actually #2562481: Apply password policies to account password elements on custom forms.
Password Policy 7.x-2.x can apply password policies to password elements on custom forms, whereas 7.x-1.x only applies password policies to a few specific, hard-coded forms. I cannot remember, but I suspect PRLP provides a custom form to which only 7.x-2.x applies password policies.
It would be useful to know if one of the 7.x-1.x patches in that issue solves this problem for you.
Comment #37
abaier commentedThanks for clarifying this. I switched to the 7.x-2.x branch after posting this and got it working now. Just hesitated to use it in alpha-state first.
I did not investigate the patches for 1.x any further, sorry.
Comment #38
nerdcore commentedJust want to share this in case others find it helpful.
I have a site which is using the Password Hustle module to provide a Password Reset form from a one-time login link. I just tried uninstalling Password Policy 1.x and installed 2.x but the rules I setup were still not enforced when using the form provided by Password Hustle.
I have reverted to Password Policy 1.x and am successfully enforcing its rules on this form having added the Form ID to the list in
password_policy_form_alter()as follows:I've already spent too much time trying to get this working to begin troubleshooting the 2.x version at this stage. It would be great if it supported the forms created by Password Hustle and other modules but I see no documentation on this available, so this hack to the 1.x module will have to suffice for now.
Comment #39
aohrvetpv commentednerdcore,
7.x-2.x will apply policies to any form that has an
$form['account']['pass']element of type'password_confirm'. A number of contributed modules with custom password forms use that structure. I'd guess that Password Hustle is using something atypical. Will investigate.7.x-1.x hardcodes specific form IDs to apply password policies to. I was hoping to change to the approach used by 7.x-2.x.
There are many modules with custom password forms so we need some general approach that does not require continually adding form IDs for every module that crops up.
Comment #40
aohrvetpv commentednerdcore, here's a Password Hustle patch that should make it work with Password Policy 7.x-2.x. It just makes the Password Hustle form more consistent with other forms that have an account password. Note that for the dynamic, JavaScript list of unmet requirements to work, the policy will need to also apply to the 'anonymous user' role.
Password Hustle might work with 7.x-1.x if this patch and the patch in #2562481-19: Apply password policies to account password elements on custom forms are applied.
Comment #41
rajab natshahThis Integration is needed for Drupal 8 too.
#2917622: Password expires (Password Reset Days) does not work
Comment #42
rajab natshah1. Introduction, Threat Models
at 18:20
https://youtu.be/GqmQg-cszw4?t=18m20s
Comment #43
rajab natshah#2924009: Apply password policies to password elements on custom forms
Comment #44
vimalabhi89 commentedis there a patch version of this that works for drupal 8?
Comment #45
dhayanandan_k commentedHere is the patch for Drupal 8 for password policy rules on PRLP form
Comment #46
dhayanandan_k commentedComment #47
mably commentedStarted implementing my compatibility fix for the prlp module in a new contrib module: https://www.drupal.org/project/password_policy_extras