LP#2018615 - LookupUser Password Auth user/stompro/lp2018615-password-check-master
authorJosh Stompro <stomproj@larl.org>
Thu, 11 May 2023 18:20:35 +0000 (13:20 -0500)
committerJosh Stompro <stomproj@larl.org>
Fri, 12 May 2023 13:27:27 +0000 (08:27 -0500)
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 <stomproj@larl.org>
README.adoc
examples/NCIP_test_messages/folio-lookupuser-password.xml [new file with mode: 0644]
examples/NCIP_test_messages/folio-lookupuser-pin.xml [new file with mode: 0644]
examples/NCIP_test_messages/folio-lookupuser.xml [new file with mode: 0644]
examples/oils_ncip.xml.example
lib/NCIP/ILS/Evergreen.pm

index 5115726..8a8af42 100644 (file)
@@ -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 (file)
index 0000000..3ca1783
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<NCIPMessage version="http://www.niso.org/schemas/ncip/v2_0/ncip_v2_0.xsd"
+   xmlns="http://www.niso.org/2008/ncip">
+  <LookupUser>
+    <InitiationHeader>
+      <FromAgencyId>
+        <AgencyId>Testing</AgencyId>
+      </FromAgencyId>
+      <ToAgencyId>
+        <AgencyId>Evergreen System</AgencyId>
+      </ToAgencyId>
+    </InitiationHeader>
+    <AuthenticationInput>
+      <AuthenticationInputData>ENTER BARCODE</AuthenticationInputData>
+      <AuthenticationDataFormatType>text</AuthenticationDataFormatType>
+      <AuthenticationInputType>barcode</AuthenticationInputType>
+    </AuthenticationInput>
+    <AuthenticationInput>
+      <AuthenticationInputData>ENTER PASSWORD</AuthenticationInputData>
+      <AuthenticationDataFormatType>text</AuthenticationDataFormatType>
+      <AuthenticationInputType>password</AuthenticationInputType>
+    </AuthenticationInput>
+    <UserElementType>Name Information</UserElementType>
+    <UserElementType>User Address Information</UserElementType>
+    <UserElementType>User Privilege</UserElementType>
+    <UserElementType>User Id</UserElementType>
+  </LookupUser>
+</NCIPMessage>
diff --git a/examples/NCIP_test_messages/folio-lookupuser-pin.xml b/examples/NCIP_test_messages/folio-lookupuser-pin.xml
new file mode 100644 (file)
index 0000000..354b151
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<NCIPMessage version="http://www.niso.org/schemas/ncip/v2_0/ncip_v2_0.xsd"
+   xmlns="http://www.niso.org/2008/ncip">
+  <LookupUser>
+    <InitiationHeader>
+      <FromAgencyId>
+        <AgencyId>Testing</AgencyId>
+      </FromAgencyId>
+      <ToAgencyId>
+        <AgencyId>Evergreen System</AgencyId>
+      </ToAgencyId>
+    </InitiationHeader>
+    <AuthenticationInput>
+      <AuthenticationInputData>ENTER BARCODE</AuthenticationInputData>
+      <AuthenticationDataFormatType>text</AuthenticationDataFormatType>
+      <AuthenticationInputType>barcode</AuthenticationInputType>
+    </AuthenticationInput>
+    <AuthenticationInput>
+      <AuthenticationInputData>ENTER PIN</AuthenticationInputData>
+      <AuthenticationDataFormatType>text</AuthenticationDataFormatType>
+      <AuthenticationInputType>PIN</AuthenticationInputType>
+    </AuthenticationInput>
+    <UserElementType>Name Information</UserElementType>
+    <UserElementType>User Address Information</UserElementType>
+    <UserElementType>User Privilege</UserElementType>
+    <UserElementType>User Id</UserElementType>
+  </LookupUser>
+</NCIPMessage>
diff --git a/examples/NCIP_test_messages/folio-lookupuser.xml b/examples/NCIP_test_messages/folio-lookupuser.xml
new file mode 100644 (file)
index 0000000..6d285af
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<NCIPMessage version="http://www.niso.org/schemas/ncip/v2_0/ncip_v2_0.xsd"
+   xmlns="http://www.niso.org/2008/ncip">
+  <LookupUser>
+    <InitiationHeader>
+      <FromAgencyId>
+        <AgencyId>Relais</AgencyId>
+      </FromAgencyId>
+      <ToAgencyId>
+        <AgencyId>Evergreen System</AgencyId>
+      </ToAgencyId>
+    </InitiationHeader>
+    <AuthenticationInput>
+      <AuthenticationInputData>BARCODE</AuthenticationInputData>
+      <AuthenticationDataFormatType>text</AuthenticationDataFormatType>
+      <AuthenticationInputType>barcode</AuthenticationInputType>
+    </AuthenticationInput>
+    <UserElementType>Name Information</UserElementType>
+    <UserElementType>User Address Information</UserElementType>
+    <UserElementType>User Privilege</UserElementType>
+    <UserElementType>User Id</UserElementType>
+  </LookupUser>
+</NCIPMessage>
index abe3c2e..58188a1 100644 (file)
@@ -66,6 +66,8 @@
         value in the database.
     -->
     <!-- <stat_cat_entry stat_cat=""></stat_cat_entry> -->
+
+    <config_placeholder note="Don't remove, fixes a config parsing error" />  
   </items>
   <!-- Configurable options for patron retrieval/validation -->
   <patrons>
       Autographics extension.
     -->
     <!-- <lookupuser_send_database_id/> -->
+
+    <!--
+    Use the open-ils.auth_proxy service for when verifying
+    a patrons' password.
+
+    The 'open-ils.auth_proxy.enabled' API also must return true.
+    -->
+    <!-- <option name='use_proxy_for_patron_auth' value='false' /> -->
+    
+    <!--
+    Require patron password for LookupUser requests
+    -->
+
+    <!-- <option name='lookupuser_password_required' value='false' /> -->
+    
+    <config_placeholder note="Don't remove, fixes a config parsing error" />  
   </patrons>
   <holds>
     <!--
 
         <abort_transit_on_cancel/>
     -->
+    <config_placeholder note="Don't remove, fixes a config parsing error" />  
   </holds>
 </ncip>
index e0f3cc4..05da9af 100644 (file)
@@ -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