Jump to content

ForgotPassword: Why so complicated?


FlorianA
 Share

Recommended Posts

I've just tried the ForgotPassword module and I wonder why the password reset process can't be smoother for the user. Especially I don't understand why there must be this "verification code" that has to be transfered manually to the password reset form. Why couldn't it be integrated directly into the URL? It shouldn't make any difference as to security since both URL and verification code are transfered through the same channel (e-mail) anyway.

I'm planning to migrate my current non-PW site to PW, and since I don't have my user's clear-text passwords, I can't migrate them, too. That means I'll have to force all my users through the password reset procedure, and I really wouldn't like to make this more tedious than necessary.

Another feature request: I'd like to confirm the additional field values in the first step (before sending the e-mail) rather than in the last one. I think this would not only improve user experience, but it would also allow to use e-mail rather than user name for identification even if there are duplicate e-mail adresses, since you could use the confirm value field for disambiguation.

  • Like 1
Link to comment
Share on other sites

First of all: for feature requests you might want to open an issue at https://github.com/processwire/processwire-requests. This is how it'll have the best likelihood of gaining the attention of Ryan ?

12 hours ago, FlorianA said:

Especially I don't understand why there must be this "verification code" that has to be transfered manually to the password reset form. Why couldn't it be integrated directly into the URL? It shouldn't make any difference as to security since both URL and verification code are transfered through the same channel (e-mail) anyway.

I do agree that a sufficiently complex and rapidly expiring initial key embedded within an URL should be enough, but saying that the verification key wouldn't add any extra security isn't, in my opinion, completely fair. The longer the key the more secure it should be, and a second verification method (particularly one that user has to enter separately) adds another layer of safety. Technically it could also a) force the user to actually read the message, and b) prevent attacks where the user is somehow fooled into clicking an URL — though I'm not sure how common attack vector this would be.

The way I see it, current implementation trades some ease of use to some extra safety, and personally I'm fine with that: password reset process should be a relatively rare occurrence, and attacks targeting such features are a common problem. (But you do make a good argument here; perhaps this should actually be a configurable setting for the module?)

12 hours ago, FlorianA said:

Another feature request: I'd like to confirm the additional field values in the first step (before sending the e-mail) rather than in the last one. I think this would not only improve user experience, but it would also allow to use e-mail rather than user name for identification even if there are duplicate e-mail adresses, since you could use the confirm value field for disambiguation.

Again I think this depends a bit on your of view: on one hand current implementation makes sure that if one just gains access to a reset link they won't be able to change the password (particularly if you ask them to confirm something other than the email field), but on the other hand some experts recommend that this step should occur before sending the reset message (exactly for the same reason — security).

Seems like another potential module setting to me, perhaps even so that both options (confirmation before and confirmation after) would be available.

12 hours ago, FlorianA said:

I'm planning to migrate my current non-PW site to PW, and since I don't have my user's clear-text passwords, I can't migrate them, too. That means I'll have to force all my users through the password reset procedure, and I really wouldn't like to make this more tedious than necessary.

Just a quick note on this one: you don't actually have to force the users to go through the password reset procedure. In a case like this it'd be relatively simple to set up a custom process to handle the initial password reset — create and send the links to your users and process them through your own code. I've done that a few times during large scale migrations, and it's not that hard to do — though in most cases I would still recommend going through the password reset feature. Personally I don't think that the process is that hard on users.

Just an idea — again I get that you're hoping to change things in general, but if you need to get this done on a timely manner, it would probably be best not to wait for a core level change. Especially since it isn't necessarily a complete no-brainer how this feature should work ?

  • Like 4
Link to comment
Share on other sites

@FlorianA, you can probably achieve what you want by using hooks. ProcessForgotPassword::renderEmailBody is hookable and includes the link URL as an argument, to which you could add the verification code (which is also an argument) as a GET parameter.

Then you could hook before InputfieldText::render and if the field name is "verify" (you could do additional checks if needed) you could check $input and set the value from the GET parameter.

  • Like 5
Link to comment
Share on other sites

  • 3 months later...

Adding some code to expand on my post above. In /site/ready.php:

// Forgot password: add verification code as a URL parameter
$wire->addHookBefore('ProcessForgotPassword::renderEmailBody', function(HookEvent $event) {
	$url = $event->arguments(0);
	$verification_code = urlencode($event->arguments(1));
	$url .= "&code=$verification_code";
	$event->arguments(0, $url);
});
// Forgot password: pre-fill verify field from URL parameter
$wire->addHookBefore('ProcessForgotPassword::renderForm', function(HookEvent $event) {
	$form = $event->arguments(0);
	$form_name = $event->arguments(1);
	if($form_name !== 'step3') return;
	$verify_field = $form->getChildByName('verify');
	if(!$verify_field) return;
	$code = $event->wire('input')->get('code');
	if(!$code) return;
	$verify_field->description = 'Please type or paste in the code you received in your email if it is not already shown below.';
	$verify_field->value = urldecode($code);
});

I just set this up on a site and it seems to be working well.

  • Like 2
Link to comment
Share on other sites

  • 10 months later...
On 5/24/2020 at 12:22 PM, Robin S said:

Adding some code to expand on my post above. In /site/ready.php:


// Forgot password: pre-fill verify field from URL parameter
$wire->addHookBefore('ProcessForgotPassword::renderForm', function(HookEvent $event) {
	$form = $event->arguments(0);
	$form_name = $event->arguments(1);
	if($form_name !== 'step3') return;
	$verify_field = $form->getChildByName('verify');
	if(!$verify_field) return;
	$code = $event->wire('input')->get('code');
	if(!$code) return;
	$verify_field->description = 'Please type or paste in the code you received in your email if it is not already shown below.';
	$verify_field->value = urldecode($code);
});

I just set this up on a site and it seems to be working well.

@Robin S While trying to get a password reset process a bit smoother, I stumbled upon your hook that looks very promising. Maybe I didn’t get it correctly, but it seems that ProcessForgotPassword::renderForm is not working. There is no method ___renderForm in ProcessForgotPassword.module, so nothing at all happens after clicking the (successfully modified) email link. When I try ProcessForgotPassword::execute instead I get at least a reaction, but I don‘t know how to select the field verify to populate. It’s not crucial, as I can live with the unsmoother copy-paste-code as well, but I would prefer to do it the way you suggested.

Link to comment
Share on other sites

19 minutes ago, rash said:

There is no method ___renderForm in ProcessForgotPassword.module

There is such a method in recent versions of PW: https://github.com/processwire/processwire/blob/d8945198f4a6a60dab23bd0462e8a6285369dcb9/wire/modules/Process/ProcessForgotPassword.module#L992-L1004

Are you maybe running an older version of PW?

Link to comment
Share on other sites

Okay, thank you – that might be an explanation, as on this particular site 3.0.142 is running. You think it would be possible to just replace ProcessForgotPassword.module? I’m not sure if I should do a complete PW update, as there are quite a few loose ends in this project at the moment and I fear to lose the overview. Worst case would be to postpone the PW reset smoothening until PW will be updated later.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...