-
Notifications
You must be signed in to change notification settings - Fork 359
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable password recovery when using ILS Authentication #3997
base: dev
Are you sure you want to change the base?
Conversation
…tion. Updated based on the PHP 8.3 test failures.
…tion. Updated based on the PHP 8.3 test failures. When I ran php cbf it made changes to the if statements that caused this failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @oharacj! See below for a few initial thoughts and questions.
@@ -2079,9 +2125,12 @@ public function newPasswordAction() | |||
} | |||
// Update hash to prevent reusing hash | |||
$this->getAuthManager()->updateUserVerifyHash($user); | |||
// Login | |||
if ($followUp = $this->followup()->retrieve('url')) { | |||
$newUrl = strstr($followUp, 'Verify', true) . 'Home'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand the purpose of this; maybe a comment is in order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that makes sense, though I'm not sure I understand exactly what $followUpUrl = strstr($followUp, 'Verify', true) . 'Home';
is trying to do. I wonder if it might be better to do something like $followUpUrl = str_contains($followUp, 'Verify') ? $this->url()->fromRoute('home') : $followUp;
(so we're using the router instead of string manipulation to pick the destination URL... but maybe I'm misunderstanding which target route is actually desired).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work without an existing VuFind account. My proposal would be to add another ILS driver method for looking up the patron with email address and card number. Since we already have a local implementation that works across ILS systems, our experience is that this allows recovery with any ILS that can do the lookup and update the password. See https://github.com/NatLibFi/NDL-VuFind2/blob/dev/module/Finna/src/Finna/ILS/Driver/KohaRest.php#L747 for our implementation with Koha.
The recovery token data and any other information needed (e.g. target ILS for MultiILS) from the lookup method can be stored in access_token table with a random hash as the id. This hash should be included in the recovery link in the email along.
Since this functionality is somewhat different from internal password recovery, it might make sense to separate the implementation. That's why we chose locally to use different method names etc.
* | ||
* @return bool | ||
*/ | ||
public function supportsPasswordRecovery() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a counterpart in MultiILS that supports checking the selected target. For inspiration:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial work is only supposed to be for the ILS auth. MultiILS is something I'll look at in the future but I'm not sure it's part of the scope of this work. Is this piece a necessity? If so, I can start working on this and I'll resubmit when I have it done. I only have one ILS and I can't really test but I'm happy to look into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could potentially use the Demo driver as a second ILS for testing purposes, if that helps! Let me know if you need more details/help to get that set up.
{ | ||
$driver = $this->getCatalog()->getDriver(); | ||
if ( | ||
method_exists($driver, 'changePassword') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest a new method for updating the password during recovery, since changePassword requires the patron from patronLogin method. Our custom code uses this:
https://github.com/NatLibFi/NDL-VuFind2/blob/dev/module/Finna/src/Finna/ILS/Driver/KohaRest.php#L792
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the code to use a resetPassword method for this. I've added my resetPassword to the SierraRest Driver.
Updated comments, line endings, follow-up edits have been put in abstractbase, explained the redirect.
updated formatting.
added trailing comma to return array
Object-Oriented Programming is a thing.
I have an ILS method called getPatronFromUsername which provides this function exactly. It has been added to the SierraRest driver.
I am partially utilising the internal password recovery methods in order to keep from duplicating functionality |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the progress, @oharacj -- see below for a few more tips, questions and ideas. :-)
config/vufind/SierraRest.ini
Outdated
@@ -59,6 +59,9 @@ use_prefixed_ids = false | |||
; used (redirect_uri above is not set). | |||
username_field = "code" | |||
password_field = "pin" | |||
; Some library systems use a four digit access pin. Others prefer to have alpha numeric | |||
; passwords. set digits_only to true for pin functionality. Default is false (alpha-num). | |||
digits_only = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are higher-level password rules defined in config.ini. I wonder if it would be beneficial to make this setting more parallel with those (especially if we could refactor code to make the password validation logic reusable -- I haven't inspected to see how feasible this is, but it seems likely to be an option).
Alternatively, if there are really only two different options in Sierra, maybe it would be more clear to call this setting four_digit_pin
(to account for both the length restriction and the content restriction), or to have a setting like password_mode = pin|password
(if we want to allow for more possibilities in the future than a binary setting can provide.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checking to see if you have any thoughts on this point, since there hasn't been further discussion on it since October. (Also happy to hear @EreMaijala's thoughts, if any).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use the same rules as when changing a password, i.e. the [changePassword] section in ILS driver's ini:
; Uncomment the following lines to enable password (PIN) change
;[changePassword]
; PIN change parameters. The default limits are taken from the interface documentation.
;minLength = 4
;maxLength = 4
; See the password_pattern/password_hint settings in the [Authentication] section
; of config.ini for notes on these settings. When set here, these will override the
; config.ini defaults when Sierra is used for authentication.
;pattern = "numeric"
;hint = "Your optional custom hint can go here."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not sure how I've managed to miss this section of the ini so many times. I had to have looked over it hundreds of times without seeing that there was a [changePassword] section. I'll remove the custom stuff I did but I'll also have to make a change to the changePassword function in the SierraRest driver in order to remove the hard-coded digits only section of password change.
* | ||
* @return bool | ||
*/ | ||
public function supportsPasswordRecovery() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could potentially use the Demo driver as a second ILS for testing purposes, if that helps! Let me know if you need more details/help to get that set up.
@@ -309,11 +309,12 @@ public function getStoredCatalogCredentials() | |||
* fails, clear the user's stored credentials so they can enter new, corrected | |||
* ones. | |||
* | |||
* Returns associative array of patron data on success, false on failure. | |||
* @param $user_name - the username/barcode for ILS password reset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor points of style: I'd suggest $username
or $userName
instead of $user_name
-- we rarely use snake_case in our code, so the other options would be more consistent. Also, you don't need the "-" separator in this comment.
@@ -2079,9 +2125,12 @@ public function newPasswordAction() | |||
} | |||
// Update hash to prevent reusing hash | |||
$this->getAuthManager()->updateUserVerifyHash($user); | |||
// Login | |||
if ($followUp = $this->followup()->retrieve('url')) { | |||
$newUrl = strstr($followUp, 'Verify', true) . 'Home'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that makes sense, though I'm not sure I understand exactly what $followUpUrl = strstr($followUp, 'Verify', true) . 'Home';
is trying to do. I wonder if it might be better to do something like $followUpUrl = str_contains($followUp, 'Verify') ? $this->url()->fromRoute('home') : $followUp;
(so we're using the router instead of string manipulation to pick the destination URL... but maybe I'm misunderstanding which target route is actually desired).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the ongoing work, @oharacj -- I started my review this morning but ran into some questions that I think will be resolved by merging the dev branch into this PR, so I decided to stop until that's done to be sure I'm reviewing everything in an up-to-date and working state. Please let me know if you run into any trouble with this!
config/vufind/SierraRest.ini
Outdated
@@ -59,6 +59,9 @@ use_prefixed_ids = false | |||
; used (redirect_uri above is not set). | |||
username_field = "code" | |||
password_field = "pin" | |||
; Some library systems use a four digit access pin. Others prefer to have alpha numeric | |||
; passwords. set digits_only to true for pin functionality. Default is false (alpha-num). | |||
digits_only = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checking to see if you have any thoughts on this point, since there hasn't been further discussion on it since October. (Also happy to hear @EreMaijala's thoughts, if any).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't have time for a full review yet, but I noticed one thing that looks like a problem and had a couple of very minor style suggestions that you can apply by just committing my suggestions from within the comments below. :-)
if (!empty($method)) { | ||
$this->getAuthManager()->setAuthMethod($method); | ||
} | ||
} $this->getAuthManager()->setAuthMethod($method); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be a formatting problem here -- did this brace get moved up a line somehow?
//This exists because the followupURL gets set to Verify which returns | ||
//an error message due to trying to check the hash a second time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor style suggestion -- add spaces after //
:
//This exists because the followupURL gets set to Verify which returns | |
//an error message due to trying to check the hash a second time | |
// This exists because the followupURL gets set to Verify which returns | |
// an error message due to trying to check the hash a second time |
<?php if (!empty($this->target)): ?> | ||
<input type="hidden" value="<?=$this->escapeHtmlAttr($this->target) ?>" name="target"> | ||
<?php endif; ?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to have some extra indentation:
<?php if (!empty($this->target)): ?> | |
<input type="hidden" value="<?=$this->escapeHtmlAttr($this->target) ?>" name="target"> | |
<?php endif; ?> | |
<?php if (!empty($this->target)): ?> | |
<input type="hidden" value="<?=$this->escapeHtmlAttr($this->target) ?>" name="target"> | |
<?php endif; ?> |
Add handling to enable password recovery when using ILS Authentication method