We authenticate users by their library barcode and their last name. Our EZProxy user authentication uses SIP to determine if a given user is valid or not. Unfortunately, Voyager's implementation of SIP does not return a patron's last name as a discrete variable. Instead, it returns the patron's full name as a single string.
At first, we didn't have any problems. EZProxy provides a function ParseName() that will split a given name into its parts. We used a check that looks like this:
Set ParseName(auth:AE, "FMS", "login")
If Upper(login:pass) ne Upper(login:surname) {
Deny loginbu.htm
}
This works as expected for most users, however users with a last name that contained a space and did not have a middle initial were being denied. For these users, the first word in their last name was being parsed as their middle initial. As a temporary fix, I just gave the user a middle initial. But there's more you can do.
The simple solution is to concatenate the middle and last names prior to the check and use the AnyWild() function to be sure the given password is found in the concatenated string. This looks like so:
Set ParseName(auth:AE, "FMS", "login")
Set passCheck = login:middleName . login:surname
If !AnyWild(passCheck, "*" . login:pass) {
Deny loginbu.htm
}
This appears to work, but isn't exactly secure. A patron only requires to provide at minimum the last character of their last name. They could of course add more characters. As an example, my last name is Stacey. I could log in using the following passwords: y
, ey
, cey
, acey
, tacey
, or stacey
. I could even keep going to include my middle initial. This opens a security risk, a user need only try all 26 letters and would have access to millions of dollars of licensed materials. I don't care, but I'm sure EBSCO does. Luckily, we can do better.
We tighten the check by also ensuring that the provided password at the very least matches the last name determined by the ParseName() function. That looks like this:
Set ParseName(auth:AE, "FMS", "login")
Set passCheck = login:middleName . login:surname
If !AnyWild(login:pass, "*" . login:surname) || !AnyWild(passCheck, "*" . login:pass) {
Deny loginbu.htm
}
At UMass Boston, we actually go one step further. We have had issues in the past concerning users with hyphens, spaces, and even apostrophes in last names. I do not know what was the limiting technology (whether it was EZProxy or how the data was queried from MS Access at the time), but we could not include these characters and they were replaced by spaces. This was very confusing for users to remember so I had written a javascript function that converted these characters for users on form submission. Now, EZProxy can do this for us. We simply eliminate all non letter characters like so:
Set ParseName(auth:AE, "FMS", "login")
Set pass = REReplace("/[^a-zA-Z]/g", "", login:pass)
Set lastCheck = REReplace("/[^a-zA-Z]/g", "", login:surname)
Set passCheck = REReplace("/[^a-zA-Z]/g", "", login:middleName . login:surname)
If !AnyWild(pass, "*" . lastCheck) || !AnyWild(passCheck, "*" . pass) {
Deny loginbu.htm
}
Now, a patron with a space in their last name must enter at least all but the first word in their last name, but may also include that first word. This has the added "feature" that users with a single word for their last name may include their middle name as well. Most importantly, more users are logging in without any problems.
User experience +1
*August 15, 2009* I've since used Faux PatronAPI to pull names from Voyager instead of relying on SIP.