Configurable patron auth and retrieval

Bug #1817645 reported by Jeff Davis
18
This bug affects 3 people
Affects Status Importance Assigned to Milestone
Evergreen
Fix Released
Wishlist
Unassigned

Bug Description

External services often need to talk to the ILS to authenticate/authorize patrons and retrieve basic information about the patron account, such as patron type, email address, or current checkouts. Different vendors have different requirements, and different libraries in a consortium may have different policies around which patrons may be authenticated and what patron info to share with the vendor. Evergreen does not currently provide an easy way to handle this.

I propose the following:

1. EG should provide a simple, secure HTTP API for authentication and retrieval of basic patron information -- something that common library vendors and products can use.

2. To accommodate the range of vendor requirements, there should be different handlers for different external services. The handler would process the incoming message, talk to the EG backend (client authorization and patron auth/retrieval), and provide an appropriate response. Responses should be configurable and template-based where applicable, so that each library has control over the information they share.

3. Libraries should be able to control which patrons can and cannot be authenticated, based on common criteria such as patron type, current status, and blocks/standing penalties.

Changed in evergreen:
importance: Undecided → Wishlist
milestone: none → 3.next
Changed in evergreen:
assignee: nobody → Jeff Davis (jdavis-sitka)
Revision history for this message
Jeff Davis (jdavis-sitka) wrote :
Download full text (6.1 KiB)

Working branch user/jeffdavis/lp1817645-remoteauth-patron-api has an initial implementation:

https://git.evergreen-ils.org/?p=working/Evergreen.git;a=shortlog;h=refs/heads/user/jeffdavis/lp1817645-remoteauth-patron-api

It introduces a generic RemoteAuth mod_perl handler for processing various types of patron auth requests, and provides a form of "Basic" HTTP Authentication [1] as a reference implementation.

This branch doesn't include templating for responses. I want to add support for EZProxy and possibly PatronAPI, but I'd like the current design and code to be reviewed before I proceed.

How it works:
-------------
1. Client submits a request to a RemoteAuth endpoint containing user credentials and any additional requirements.
2. RemoteAuth loads the handler module for this endpoint.
3. Handler processes the request and authorizes the client.
4. Handler loads this endpoint's configuration from the database.
5. Handler authenticates the user using the credentials provided, and tests whether auth is permitted for this user at this endpoint.
6. Handler returns an appropriate response to RemoteAuth, which passes the response to the client.

Test plan for Basic HTTP Authentication:
----------------------------------------
1. Install the branch on a test server and load concerto data. Basic auth will be enabled by default for localhost access only.
2. Generate base64-encoded credentials for your test patron: echo -n "<username>:<password>" | base64
3. Query the basic auth endpoint: curl -k -s -o /dev/null -I -w "%{http_code}\n" https://localhost/api/basicauth -H "Authorization: Basic <base64-encoded-credentials>"

This will return 200 if patron authentication is successful, and 403 if patron auth fails or is not permitted.

There's also a Perl live test. However, the live test may fail in some environments due to an upstream bug in LWP::Protocol::https that prevents us from skipping certificate verification.[2] The packaged version of that module in Ubuntu 16.04 is affected; installing LWP::Protocol::https version >=6.07 from CPAN resolves the problem.

Apache configuration:
---------------------
To define a new RemoteAuth endpoint, add a new Location directive in your eg_vhost.conf file. The default configuration for Basic auth looks like this:

<Location /api/basicauth>
    SetHandler perl-script
    PerlHandler OpenILS::WWW::RemoteAuth
    Options +ExecCGI

    # access restricted to localhost by default; since this module provides no
    # client authentiation, restricting access by IP or other means is stongly
    # recommended
    Require local

    # remoteauth config name
    PerlSetVar OILSRemoteAuthConfig "Basic"
    # Perl module for processing requests
    PerlSetVar OILSRemoteAuthHandler "OpenILS::WWW::RemoteAuth::Basic"

    # staff username/password for config lookup and patron retrieval
    PerlSetVar OILSRemoteAuthClientUsername "admin"
    PerlSetVar OILSRemoteAuthClientPassword "demo123"
</Location>

The URL path /api/basicauth is our endpoint. External clients send appropriately-constructed requests to this URL and get a response indicating whether auth succeeded (and containing patron account information, dependi...

Read more...

tags: added: pullrequest
Revision history for this message
Jeff Davis (jdavis-sitka) wrote :

Sorry, under "Apache configuration" above, "OILSRemoteAuthConfig" above should be "OILSRemoteAuthProfile". When I add documentation it will use the correct name.

Revision history for this message
Jeff Davis (jdavis-sitka) wrote :

Force-pushed a few tweaks (like returning the user object on successful patron auth so that future handlers can use it). And now I'm un-assigning myself from this bug and leaving it alone for review.

Changed in evergreen:
assignee: Jeff Davis (jdavis-sitka) → nobody
Revision history for this message
Jeff Davis (jdavis-sitka) wrote :

TechRef documentation has been pushed to the working branch.

Some questions to consider:

- Is mod_perl the right tool? I chose it to avoid introducing new dependencies.

- Would it make more sense for each authentication type to use a different mod_perl handler, rather than having all auth endpoints use OpenILS::WWW::RemoteAuth as the handler? Using the same handler simplifies some configuration and hopefully allows Apache processes to be reused by different endpoints, but maybe distinct handlers are preferable.

- Will the current design handle a high volume of patron auth requests?

- Are there any reasonable use cases that can't be accommodated by the current design? So far you can restrict authentication by home library, usergroup (by requiring a perm that is only granted to certain usergroups), blocks/standing penalties, and active/expired status.

- To make live tests work, a default EG install will have a Basic HTTP Authentication endpoint at /api/remoteauth, restricted to local access only. Is that OK (and if not, how do we do live tests)? Do we want to use a different URL path?

- Is there a better way to manage the disparate authentication requirements of library vendors?

tags: added: needsdiscussion
Changed in evergreen:
milestone: 3.next → 3.4-beta1
Revision history for this message
Galen Charlton (gmc) wrote :
Revision history for this message
Galen Charlton (gmc) wrote :

But the quick summary:

- I like this.
- I expect it to be reasonably performant; if it gets heavily used, spinning up an Apache instance just for managing patron auth is an option for an EG admin
- Does adding a per-user opt-in/out mechanism make any sense?
- I suggest adding an Angular admin interface for config.remote_auth
- I suggest defining and using a new user activity type.

Revision history for this message
Galen Charlton (gmc) wrote :

And a blue-sky suggestion, probably for later: add something to the patron's My Account pages that tells them when their credentials have been used last, both for direct Evergreen login and for authentication for other services.

Andrea Neiman (aneiman)
tags: added: authentication
tags: removed: needsdiscussion
Changed in evergreen:
assignee: nobody → Jeff Davis (jdavis-sitka)
Revision history for this message
Jeff Davis (jdavis-sitka) wrote :

Working branch user/jeffdavis/lp1817645-remoteauth-patron-api-squashed-rebased has some updates:

- The code has been rebased to current master.

- A UI for managing authentication profiles has been added to the staff client.

- You can now specify a user activity type for your authentication profiles. When a user is authenticated via a RemoteAuth endpoint, the request will be recorded in user activity using the user activity type associated with that endpoint's authentication profile. (There is no new default user activity type for RemoteAuth, since different libraries will have different needs when it comes to tracking user activity.)

The admin UI is auto-generated by Angular. Unfortunately the User Activity Type selector displays the id of the various user activity types, which is not very helpful; it ought to display the label. Do we need a specialized User Activity Type component for this? How would you implement that in an auto-generated UI?

I also see two problems that appear to affect all auto-generated server admin UIs, not just RemoteAuth: (1) When the content of a previously-populated text field is deleted, the field is saved to the database as an empty string, not as a null value. (2) The tabular summary shows "Yes" for all boolean fields, regardless of the actual value.

I have not added an opt-in/opt-out setting or the ability for users to view their activity in My Account. Those would be great features, and I hope to work on them in future, but I don't think they are essential and I'd like to focus on getting the core RemoteAuth functionality committed first.

Changed in evergreen:
assignee: Jeff Davis (jdavis-sitka) → nobody
Revision history for this message
Galen Charlton (gmc) wrote : Re: [Bug 1817645] Re: Configurable patron auth and retrieval

> The admin UI is auto-generated by Angular. Unfortunately the User
> Activity Type selector displays the id of the various user activity
> types, which is not very helpful; it ought to display the label. Do we
> need a specialized User Activity Type component for this? How would you
> implement that in an auto-generated UI?

Adding a reporter:selector attribute to the IDL definition of the ID field
for cuat should fix this.

> (2) The tabular summary shows
> "Yes" for all boolean fields, regardless of the actual value.

I ran across this bug in a different context and will be writing a patch
for it shortly.

Revision history for this message
Galen Charlton (gmc) wrote :

I've opened bug 1833080 for the eg-bool bug.

Revision history for this message
Jeff Davis (jdavis-sitka) wrote :

Thanks, Galen. I've pushed an additional commit to the working branch, adding the appropriate reporter:selector attribute. It works for me.

Galen Charlton (gmc)
Changed in evergreen:
assignee: nobody → Galen Charlton (gmc)
status: New → Confirmed
Revision history for this message
Galen Charlton (gmc) wrote :

Merged to master for inclusion in 3.4. Thanks, Jeff!

There are a couple errata that should be fixed for the release candidate:

- the 'allow inactive' option doesn't work. Looks like non-SUCCESS returns from open-ils.auth.login may need to be checked more precisely.
- a SERIAL primary key on config.remoteauth_profile would be good rather than the natural one so that eg-edit-fm-record can handle changing the name of a rule.

Changed in evergreen:
assignee: Galen Charlton (gmc) → nobody
status: Confirmed → Fix Committed
Galen Charlton (gmc)
Changed in evergreen:
status: Fix Committed → Fix Released
Revision history for this message
Jeff Davis (jdavis-sitka) wrote :

See bug 1843818 for addressing Galen's errata and any other small fixes.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.