Invent a page in the OPAC for redirection to referring URL based authentication on external services such as EBSCO

Bug #1552409 reported by Blake GH on 2016-03-02
14
This bug affects 2 people
Affects Status Importance Assigned to Milestone
Evergreen
Undecided
Unassigned

Bug Description

We have ran into a issue with EBSCO. They do not support SIP2 (yet) authentication. EBSCO supports these methods:
http://support.epnet.com/knowledge_base/detail.php?id=3572

Patrons accessing the E-books from their home, cannot rely on IP authentication. In a consortium setting where ALL of the libraries are participating in an E-book program, it's not feasible to convey a uniformed patron barcode regular expression. We really don't want to force the patrons to have some sort of EBSCO login credentials (causing more pain for the patron). The best option is probably referring URL. Which would work if they simply clicked the URL from the OPAC, except EBSCO wants that referring URL to be a URL that requires a login.

We could devise a simple OPAC page that forces the Evergreen authentication, and upon successful login, redirect to the intended URL to the electronic resource. This of course, would require that all of the subfield $9's be updated to the auth page. Something like this:

https://domain/eg/opac/referringurl?intendedurl=http://search.ebscohost.com/login.aspx?authtype=url&db=nlabk&AN=331285

Once in place, the click will send the patron back to the OPAC, prompt for the login (or not if they are already logged in), and redirect to the {intendedurl} - the code could also do things like make sure that the patron is in good standing.

Any thoughts on the idea?

Thomas Berezansky (tsbere) wrote :

I am under the impression that referring URL from https is, in may cases, not possible to use for authentication. As such this would, in theory, not actually work to authenticate. Have you confirmed it actually functions in current browsers (as in, the http referrer actually gets set)?

Blake GH (bmagic) wrote :

Thomas,
That was one of the things we addressed with EBSCO in this case. It turns out if it's https -> https, it works as per the RFC. Chrome keeps the referring url headers during a 301 but FF does not. Therefore, we used JS to load the final URL from the opac, which works in FF and Chrome. The headers are intact and it's working! The electronic resources are accessible!

Thomas Berezansky (tsbere) wrote :

Beyond the referring url not always being sent (your example seems to be a http page, and a lot of services don't have https landing pages) I also question the use of referring url for authentication in the first place. The number of security packages that look to ensure that they don't get set is fairly high.

Furthermore, the *way* you are directing people is, itself, easy enough to use for visitors without the ability to login to "spoof" the referrer (as the final destination is readily available in the url, and referrer spoofing is fairly easy).

If we ignore authenticating via referring url as a problem itself then I would think the better way to handle this would be to store the actual destination URL in the server, either as a DB setting or apache config setting, rather than in the link to the redirector page.

A quick and easy way to "store" the redirection(s) (without checking anything beyond "you can log in") would be "create a new template file that does nothing but point you, with javascript and a link in case javascript is disabled, to the final destination page". Because new template files require authentication by default you need no new perl code to make it work.

Also, I just realized, you have talked about FF and Chrome, but what about IE and/or Safari?

Blake GH (bmagic) wrote :

Thomas,

This code is confirmed working in Opera, Firefox, Chrome, OSX Safari.
I like the idea of just implementing the whole thing in TT. I utilized the perl module to set some variables to make the code easier to understand in TT. However, I believe all of those uri regular expressions could be moved out of the perl module and put into the Template Toolkit. The login form contains a blurb at the top when the authentication prompt was caused by the attempt to access. I already put some regex in TT to inject the title of the resource into the URL for user clarity.

I also like the idea of the hidden url which is only revealed after login (and therefore not publicly visible.). That had crossed my mind. That would require some perl additions? The URL of the desired 856$u would still need to be changed to the generic OPAC link which would take the browser through the login, then redirect to the secret url which is supported by a template file of the same name. The external URL would need to live through all of that. If we are going to make changes to EGCatLoader.pm for secret url reasons then we might as well leave those two functions and keep the smaller TT changes?

Thomas Berezansky (tsbere) wrote :

If we define things as being part of an online "service" (I am being lazy in coming up with a better name) then a new (or existing, I suppose) template file could use the CGI functionality to pull that "service" out. We can then use OU settings for other pieces via the get_org_setting helper:

targetservice = CGI.param('service');
targetservicename = ctx.get_org_setting(ctx.physical_loc || ctx.aou_tree.id, 'some.setting.${targetservice}.name');
targetserviceurl = ctx.get_org_setting(ctx.physical_loc || ctx.aou_tree.id, 'some.setting.${targetservice}.url');

Then do what you want/need to send them to targetserviceurl. Different template files could be created for specific services as well (say you want to attempt "In Library" versus "At Home" links, adding an introductory page, some services you want auto redirect and others manual selection (post values maybe?), or perhaps you want a giant landing page that covers multiple destinations like hotlinking deeper into Ebsco versus the main "select a product" landing page). If you throw the user's home library id into there (before ctx.physical_loc, perhaps) then you could have org unit specific urls for a given service, and throw a "We're sorry, but your library does not subscribe to ${targetservice}" message up if there is no global URL for that service.

The login page could get that "targetservice" via something like the below (in the existing login.tt2 template) and if a value is found do the same "some.setting.${targerservice}.name" lookup above to indicate what they are logging in to reach in a more human-readable form.

IF CGI.param('redirect_to').search('\?.*service=');
redirectcgi = CGI.new(CGI.param('redirect_to').replace('^.*?\?',''));
targetservice = redirectcgi.param('service');
<do other stuff here>
END;

Up to this point I don't think any of this requires any perl layer changes at all, just some template work and MARC that points at the appropriate URL.

Justin Hopkins (hopkinsju) wrote :

I'll admit that I hadn't considered privacy tools that block sending of the referrer. I'm sure the number of options to do this is high, I'm not sure what the actual adoption level is. I consider myself fairly tuned into privacy issues and this isn't something I've considered doing. That said, I do think this is an important issue and, if possible, we should make an effort to detect if this is happening by adding a check to the referrer page that checks for the existence of the header from the initial click and/or login form. I'm sure there are other/better solutions, so we should discuss.

The issue of this being easily spoofable doesn't seem like something we should be overly concerned about. This is an inherently insecure method, and the vendor knows it. In fact, I've had a discussion with another vendor (who doesn't even require the referring page to be behind a login) and expressed my shock that they'd even allow it. They realize that this is a method to keep honest people honest. Adding another layer of obfuscation and another redirection seems to me like upgrading your bike security by going from this: http://i.imgur.com/7ezRPCE.jpg to this: http://gallery.roadbikereview.com/data/roadbike/500/bike-lock.jpg

So, if we're going to do referring URL, then I'm happy with what Blake's put together. At least, the broad strokes. It sounds like the specifics of the implementation could be improved.

When we started talking options here, I had mentioned the blue sky idea of adding a Proxy/URL-Rewriting feature to Evergreen. There's another software out there doing a bang up job of this already, which many (many, many) libraries are paying for in addition to their ILS. I think this would be a better solution overall as it's more secure and a more widely supported method. Obviously the complexity is much greater - but I wonder if it's a discussion worth having whether or not we move forward with the redirection method Blake has put together.

Thomas Berezansky (tsbere) wrote :

For reference I will throw this out:

http://docs.evergreen-ils.org/2.8/_apache_access_handler_perl_module.html

The "Proxying Websites" example would be a Proxy/URL-Rewriting feature, I believe.

Dan Wells (dbw2) on 2017-05-19
Changed in evergreen:
assignee: nobody → Dan Wells (dbw2)
Dan Wells (dbw2) wrote :

Thanks, Blake, for offering up this feature. A few comments:

1) A lot of the above discussion here is about the use of referring URL to authenticate and provide access. I fully agree with Thomas that it isn't real security, but I also fully agree with Justin that this is beside the point. Many (most?) library vendors already allow it, so we should take advantage of that where we can and not over-complicate things.

2) The implementation here looks solid. One concern I have is that we appear to be using some "homemade" URL component encoding and GET param parsing. We should probably be encoding/decoding the destination as a genuine URL component instead.

3) This redirect should be optional. I don't think YAOUS is needed, just a quick option in config.tt2.

4) Opinion only, but "intendedurl" feels funny for the param name. Maybe 'destination', or 'goto'? Just a thought.

5) This will need documentation, particularly the https wrinkle. In fact, the current code's mass change of everything to https at the destination is going to box in any library who needs the referrer for some links but needs good-old http for others. It almost seems better just leave the protocol as-is from the record, and require changes to https on the data-side where needed. Any better ideas here?

tags: added: needsreleasenote
Changed in evergreen:
assignee: Dan Wells (dbw2) → nobody
Blake GH (bmagic) wrote :

Dan,

2. It's been a long time since I worked on this code, but a memory is coming to me. I checked into the encoding and I believe that the URL is conveyed to the template toolkit encoded. bre.marc has the urls htmlentitized. Perhaps the template toolkit still needs to convert it to htmlentities. If so, where is the function? Do we have a ready-made function in TT2? This touches on the topic: http://www.template-toolkit.org/docs/manual/Directives.html

3. It may not be clear, but the redirect only works when the 856$u is crafted in the MARC. This patch assumes that the library is replacing the 856$u. Example:
/(.*)/\/eg\/opac\/referringurl?intendedurl=$1
In other words, prefixing the URL with "/eg/opac/referringurl?intendedurl="
Therefore, only MARC that has been imported or otherwise altered will receive this login prompt when clicked.

4. I don't come up with the best of names while in development. I am open to anything.

5. You're right, in order to work properly, the destination URL needs to be https, which is enforced in the code, so the library doesn't need to worry about that. They do need to understand that the external vendor needs to accept the connection over SSL. Shame on vendors who are not using SSL when delivering electronic resources.

Blake GH (bmagic) wrote :

Rebased to master just now.

Jane Sandberg (sandbej) wrote :

Thanks for putting this together, Blake. I agree that a config.tt2 option to turn this on and off would be helpful. Once we get to the release notes stage, it would be very helpful to note that the destination URL needs to be https.

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

Other bug subscribers