From 761dbd82831f0bbd709947a5cd96767349986fb3 Mon Sep 17 00:00:00 2001 From: Josh Stompro Date: Thu, 11 May 2023 13:20:35 -0500 Subject: [PATCH] LP#2018615 - LookupUser Password Auth Adds support for checking passwords or PIN in the LookupUser message. * Supports making passwords mandatory for the LookupUser Message. * Supports auth-proxy with similar options as LP#1526558 * Includes a fix for the oils_ncip.xml config error mentioned in readme. * Includes some testing messages from the Folio.org mod-ncip project. * https://github.com/folio-org/mod-ncip/tree/master/docs/sampleNcipMessages oils_ncip.xlm fix - seems like as long as there is one non commened out entry in a section, then the bug that would put the commented out portion in the config data doesn't get triggered. I haven't tested any of the auth-proxy settings since I don't use that. But I enabled the option and can confirm that it still seems to work even when the auth-proxy enabled api call is used to check if the feature is enabled. Tested LookupUser Messages * Barcode only * Barcode and Password * Barcode and PIN * Barcode only with lookupuser_require_password enabled. * Barcode and Password with lookupuser_require_password enabled. Signed-off-by: Josh Stompro --- README.adoc | 22 +++- .../folio-lookupuser-password.xml | 28 +++++ .../NCIP_test_messages/folio-lookupuser-pin.xml | 28 +++++ examples/NCIP_test_messages/folio-lookupuser.xml | 23 ++++ examples/oils_ncip.xml.example | 19 ++++ lib/NCIP/ILS/Evergreen.pm | 124 +++++++++++++++++++++ 6 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 examples/NCIP_test_messages/folio-lookupuser-password.xml create mode 100644 examples/NCIP_test_messages/folio-lookupuser-pin.xml create mode 100644 examples/NCIP_test_messages/folio-lookupuser.xml diff --git a/README.adoc b/README.adoc index 5115726..8a8af42 100644 --- a/README.adoc +++ b/README.adoc @@ -334,7 +334,26 @@ ignored: You might want to do this in order to have the group name as a reminder to the person that edits the configuration. - + +lookupuser_send_database_id +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Return the database id of a patron in the lookupuser response. Returns +'UniqueID' instead of 'Barcode' in the UserIdentifierType. + +use_proxy_for_patron_auth +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Allow using the auth-proxy for patron barcode authentication. This prevents +the service from performing a 'open-ils.auth_proxy.enabled' lookup for each +request. Uncomment and Set to 'true' to enable. + +lookupuser_password_required +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Require patron password be included in LookupUser message. +Uncomment and Set to 'true' to enable. + Holds ~~~~~ @@ -418,3 +437,4 @@ will need to change that entry to whatever your vendor uses. You can more Allow from or Require ip entries for other vendors and/or hosts. It is also a good idea to allow of your own ips to connect for testing purposes. + diff --git a/examples/NCIP_test_messages/folio-lookupuser-password.xml b/examples/NCIP_test_messages/folio-lookupuser-password.xml new file mode 100644 index 0000000..3ca1783 --- /dev/null +++ b/examples/NCIP_test_messages/folio-lookupuser-password.xml @@ -0,0 +1,28 @@ + + + + + + Testing + + + Evergreen System + + + + ENTER BARCODE + text + barcode + + + ENTER PASSWORD + text + password + + Name Information + User Address Information + User Privilege + User Id + + diff --git a/examples/NCIP_test_messages/folio-lookupuser-pin.xml b/examples/NCIP_test_messages/folio-lookupuser-pin.xml new file mode 100644 index 0000000..354b151 --- /dev/null +++ b/examples/NCIP_test_messages/folio-lookupuser-pin.xml @@ -0,0 +1,28 @@ + + + + + + Testing + + + Evergreen System + + + + ENTER BARCODE + text + barcode + + + ENTER PIN + text + PIN + + Name Information + User Address Information + User Privilege + User Id + + diff --git a/examples/NCIP_test_messages/folio-lookupuser.xml b/examples/NCIP_test_messages/folio-lookupuser.xml new file mode 100644 index 0000000..6d285af --- /dev/null +++ b/examples/NCIP_test_messages/folio-lookupuser.xml @@ -0,0 +1,23 @@ + + + + + + Relais + + + Evergreen System + + + + BARCODE + text + barcode + + Name Information + User Address Information + User Privilege + User Id + + diff --git a/examples/oils_ncip.xml.example b/examples/oils_ncip.xml.example index abe3c2e..58188a1 100644 --- a/examples/oils_ncip.xml.example +++ b/examples/oils_ncip.xml.example @@ -66,6 +66,8 @@ value in the database. --> + + @@ -102,6 +104,22 @@ Autographics extension. --> + + + + + + + + + + diff --git a/lib/NCIP/ILS/Evergreen.pm b/lib/NCIP/ILS/Evergreen.pm index e0f3cc4..05da9af 100644 --- a/lib/NCIP/ILS/Evergreen.pm +++ b/lib/NCIP/ILS/Evergreen.pm @@ -160,6 +160,26 @@ sub lookupuser { return $response; } + # Check User Authentication and error out if needed. + ## TODO - Move this into check_user_auth + ## Not sure what vendor would expect in error right now. + ## True = authenticated or not checked. + ## Userid if auth success or -1 if not checked. + ## False = Auth failed or missing when required. + my $authstatus = $self->check_user_auth($request); + if(!$authstatus) { + my $problem = NCIP::Problem->new(); + $problem->ProblemType('Authentication Problem'); + $problem->ProblemDetail("User with barcode $barcode failed authentication"); + $problem->ProblemElement($idfield); + $problem->ProblemValue($barcode); + $response->problem($problem); + return $response; + } + + ##Should this check to see if the check_user_auth userid = + ##the retrieve_user_by_barcode result? + # We got the information, so lets fill in our userdata. my $userdata = NCIP::User->new(); @@ -2763,6 +2783,110 @@ sub copy_can_circulate { return ($U->is_true($copy->circulate()) && $U->is_true($location->circulate())); } +=head2 check_user_auth + + $Authorized = $ils->check_user_auth($request); + +Check if a supplied password or pin is valid. Mainly for LookupUser message. + +If the Lookup User message doesn't include a password or PIN, return -1. Unless +we require authentication, then return undef. + +Return user id if password or PIN is valid for patron. + +Return undef if password or PIN is invalid. + +=cut + +sub check_user_auth { + my $self = shift; + my $request = shift; + + ## Assume this is a LookupUser Request + + my $field = 'AuthenticationInputData'; + my $authinput = $request->{'LookupUser'}->{AuthenticationInput}; + my $password; + my $barcode; + + # Convert to array ref if it isn't already. + if (ref $authinput ne 'ARRAY') { + $authinput = [$authinput]; + } + foreach my $input (@$authinput) { + if ($input->{AuthenticationInputType} =~ /barcode/i) { + $barcode = $input->{$field}; + next; #order of elements unknown, check them all + } elsif ($input->{AuthenticationInputType} =~ /password|pin/i) { + $password = $input->{$field}; + next; #order of elements unknown, check them all + } + } + + #Check on require password setting in here also + my $require_password = + $self->{config}->{patrons}->{lookupuser_password_required} || 'false'; + return undef if(!$password && $require_password =~ /true/i); + + #password not found in message so we return -1 + return -1 if(!$password ); + + ## Check if barcode and password are valid. + ### Copied and modified from TADL iNCIPit branch + ## that branch looks like it is from Galen. + + my $args = { + type => 'opac', # + username => $barcode, + password => $password + }; + + #Check if auth proxy is allowed + my $use_proxy_for_patron_auth = + $self->{config}->{patrons}->{use_proxy_for_patron_auth} || 'false'; + + ## Check if NCIP Config enables using the auth proxy + my $auth_proxy_enabled = 0; + if ($use_proxy_for_patron_auth =~ /true/i) { + eval { + $auth_proxy_enabled = $U->simplereq( + 'open-ils.auth_proxy', + 'open-ils.auth_proxy.enabled' + ); + }; + } + + my $response; + if ($auth_proxy_enabled) { + $response = $U->simplereq( + 'open-ils.auth_proxy', + 'open-ils.auth_proxy.login', $args); + } else { + $response = $U->simplereq( + 'open-ils.auth', + 'open-ils.auth.login', $args); + } + if($U->event_code($response)) { + return undef; + } + + # get basic patron info via user authtoken + my $authtoken = $response->{payload}->{authtoken}; + my $user = $U->simplereq( + 'open-ils.auth', + 'open-ils.auth.session.retrieve', $authtoken); + if (!$user or $U->event_code($user)) { + return undef; + } + # don't leave an extra session hanging around + # for this user + $U->simplereq( + 'open-ils.auth', + 'open-ils.auth.session.delete', $authtoken); + return $user->id; + +} + =head1 OVERRIDDEN PARENT METHODS =head2 find_user_barcode -- 2.11.0