Configurable patron auth and retrieval

Bug #1817645 reported by Jeff Davis on 2019-02-26
This bug affects 2 people
Affects Status Importance Assigned to Milestone

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 →
Changed in evergreen:
assignee: nobody → Jeff Davis (jdavis-sitka)
Jeff Davis (jdavis-sitka) wrote :
Download full text (6.1 KiB)

Working branch user/jeffdavis/lp1817645-remoteauth-patron-api has an initial implementation:;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"

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...


tags: added: pullrequest
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.

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
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.4-beta1
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.

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) on 2019-04-16
tags: added: authentication
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Remote bug watches

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