Creating an LDAP Patron Authentication Adaptor Michael Doran, Systems Librarian University of Texas at Arlington Endeavor Users Group Meeting, Chicago, IL Session 46, Friday, 21 April 2006 (using Perl)
Michael Doran - University of Texas at Arlington - EndUser Why do external authentication? The default WebVoy á ge authentication is inherently insecure since login as a particular user requires credentials (last name and either SSN/Institution ID/barcode number) that are potentially known to people other than that user. External authentication login requires a password known only to a particular user.
Michael Doran - University of Texas at Arlington - EndUser Voyager external authentication Part 2 In “Part 1” [1] we learned that external patron authentication was... [1] “Overview of Voyager External Patron Authentication”Overview of Voyager External Patron Authentication EndUser 2005, Technical Session 20 Not something to be switched on......but rather something that had to be built.
Michael Doran - University of Texas at Arlington - EndUser Now where did I put that adaptor? Patron authentication adaptor feature “functionality that allows WebVoyáge to communicate with an external authentication program, via a customer-developed authentication adaptor” Patron authentication adaptor “the customer-developed adaptor which provides the communications bridge between WebVoyáge and the external authentication program” The patron authentication adaptor referred to is a computer program. Customer-developed means you get to write it.
Michael Doran - University of Texas at Arlington - EndUser Quick Review Pwebrecon.cgi opac.ini [ExtAuthenticationSystem] ExtAuthSystemEnabled=Y ExtAuthBypassLoginScreen=Y ExtAuthSystemURL=login.cgi
Michael Doran - University of Texas at Arlington - EndUser Quick Review doran ******** login.cgi generates a form......authenticates credentials via an LDAP server......and tells WebVoyáge to display patron info
Michael Doran - University of Texas at Arlington - EndUser Authentication adaptor tasks Parse and store WebVoyáge query string Generate HTML code for a patron login form Query external authentication server Insert entry into Voyager database table Return control (and query string) to WebVoyáge
Michael Doran - University of Texas at Arlington - EndUser From theory to concrete example Example: an LDAP adaptor written in Perl Do you have to use LDAP? – No CAS Kerberos whatever Do you have to use Perl? – No JSP ColdFusion PHP whatever
Michael Doran - University of Texas at Arlington - EndUser Authentication adaptor tasks Parse and store WebVoyáge query string Perl CGI module (however not used in example) Generate HTML code for a patron login form Perl CGI module (however not used in example) Query external authentication server Perl Net::LDAP module Insert entry into Voyager database table Perl DBI & DBD::Oracle modules Return control (and query string) to WebVoyáge Perl has the necessary “tool set”
Michael Doran - University of Texas at Arlington - EndUser Perl modules Perl comes with the CGI module Endeavor should have installed the DBI and DBD::Oracle modules on your database server, but they probably won’t be on your WebVoy á ge server. You’ll almost certainly have to install Net::LDAP and it will have other prerequisite modules. If you plan on encrypting your LDAP transactions (highly recommended), you’ll likely also need OpenSSL (not a Perl module)
Michael Doran - University of Texas at Arlington - EndUser The split server decision Separate Voyager database and WebVoy á ge servers? Should the adaptor go on... the Voyager database server... already has Perl DBI & DBD::Oracle modules security considerations – behind firewall? or the WebVoy á ge server? need to install Perl DBI & DBD::Oracle modules DBD requires (minimal) Oracle client installation Testing on (integrated) Voyager test server
Michael Doran - University of Texas at Arlington - EndUser The adaptor script Line-by-line analysis of the entire source code
Michael Doran - University of Texas at Arlington - EndUser Optional adaptor requirements Bypass default Voyager authentication, yet offer it as an alternative... i.e. both standard and external authentication on same form. Adaptor login form “works” even if not invoked by WebVoy á ge. LDAP server failover redundancy. Encrypt LDAP authentication sessions. Adaptor login screen has working WebVoy á ge buttons. Clean up orphan entries in Voyager “wopac” table (an oxymoron?)
Michael Doran - University of Texas at Arlington - EndUser Two, two, two forms in one! One web page... two login methods
Michael Doran - University of Texas at Arlington - EndUser Relevant code snippets $pid = $formdata{'PID'}; $seq = $formdata{'SEQ'}; $pweb_page = $formdata{'PAGE'}; sub PrintLoginForm { print qq(yada, yada); print qq(\t \n); print qq(yada, yada); } PID, SEQ, and PAGE are key-value pairs in the original query string
Michael Doran - University of Texas at Arlington - EndUser Reach out and touch someone Pwebrecon.cgi
Michael Doran - University of Texas at Arlington - EndUser Relevant code snippet # Logic on what to do based on the input if ($external) { &AuthenticatePatron("$patron_ext_username", "$patron_ext_password"); } else { if ($pid) { &PrintLoginForm; } else { # If the login script URL is bookmarked, this will get it via # a detour thru Pwebrecon.cgi in order to pick up a valid PID print "Location: $webvoyage_base_URL/cgi-bin/Pwebrecon.cgi?DB=local&PAGE=pbLogon\n\n"; }
Michael Doran - University of Texas at Arlington - EndUser You’re the one that I want... ldap.uta.edu load balancer pi.uta.edu LDAP server xi.uta.edu LDAP server LDAP redundancy LDAP query
Michael Doran - University of Texas at Arlington - EndUser LDAP redundancy in the adaptor # LDAP server variables # # University of Texas at Arlington LDAP servers: #ldap.cedar.uta.edu - LDAP server load balancer #pi.cedar.uta.edu - individual LDAP server #xi.cedar.uta.edu - individual LDAP server # # Connection approaches: # OK: Connect to an individual LDAP server. # Better: Connect to a LDAP server load balancer (if your campus has one). # This will distribute the load among available LDAPservers and # authentication will succeed even if one of the individual LDAP servers # is unavailable. # Best: Per the Net::LDAP documentation, create a list (array) of LDAP servers, # putting the LDAP load balancing host first, followed by the individual LDAP # servers. Reference the array, and connect to the array reference. Each # host in the list will be tried in order until a connection is made. This avoids # a single point of failure of either an individual LDAP server *or* the LDAP # load balancer.
Michael Doran - University of Texas at Arlington - EndUser Relevant code snippet # List (array) of LDAP servers and array reference = ('ldap.cedar.uta.edu', 'pi.cedar.uta.edu', 'xi.cedar.uta.edu'); my $rldap_server = # Create a new Net::LDAP object and open a connection # to an LDAP server. my $ldap = Net::LDAP->new( $rldap_server, version => 3, port => 389, debug => 0 ) or
Michael Doran - University of Texas at Arlington - EndUser Security is as security does ldap serverVoyager server w/ adaptor LDAP query username/password encrypted session LDAPS or TLS username/password SSL
Michael Doran - University of Texas at Arlington - EndUser Transport Layer Security (TLS) # The start_tls method converts the existing connection to # Transport Layer Security (TLS), which provides encrypted # traffic. It is an alternative to using LDAPS. # The verify options are 'none', 'optional', and 'require'. # The most secure option is 'require'. # If you set verify to optional or require, you must also set # either cafile or capath. If you have installed Apache with # SSL, you can probably use the ca-bundle.crt as your cafile # file, but make sure it has the necessary read permissions.
Michael Doran - University of Texas at Arlington - EndUser Relevant code snippets # Create a new Net::LDAP object and open a connection # to an LDAP server. my $ldap = Net::LDAP->new( $rldap_server, version => 3, port => 389, debug => 0 ) or my $mesg = $ldap->start_tls( verify => 'require', cafile => '/usr/local/apache/conf/ssl.crt/ca-bundle.crt' ); $mesg = $ldap->bind("$user", password => "$pw");
Michael Doran - University of Texas at Arlington - EndUser Working WebVoy á ge buttons Adaptor generated login page Can’t use static URLs for button links
Michael Doran - University of Texas at Arlington - EndUser Relevant code snippet ############################################################ # PrintButtons ############################################################ sub PrintButtons { print <<EOF; EOF }
Michael Doran - University of Texas at Arlington - EndUser Failure is an orphan Aborted login attempts can result in “orphan” entries in the wopac_pid_patron_keys table These orphan entries have the potential to prevent a subsequent login The adaptor should delete any orphan entries that could prevent authentication by that user SQL> select * from xxxdb.wopac_pid_patron_keys; PID PATRON_KEY
Michael Doran - University of Texas at Arlington - EndUser Relevant code snippet # Clean out any "orphan" entries in the wopac_pid_patron_keys table # that are associated with this patron. my $sql_string = "delete from $db_name. wopac_pid_patron_keys where $db_name. wopac_pid_patron_keys.pid = '$pid' or $db_name. wopac_pid_patron_keys.patron_key = '$institution_id'"; $sth = $dbh->prepare($sql_string) || warn $dbh->errstr; $sth->execute || warn $dbh->errstr;
Michael Doran - University of Texas at Arlington - EndUser Includes Consider putting the static HTML code (e.g. for portions of the web login form) in “include” files outside of your script This keeps the script lean and allows you to easily view and validate the HTML portion by concatenating the include files together and viewing the resulting file in a browser
Michael Doran - University of Texas at Arlington - EndUser Relevant code snippet sub PrintLoginForm { # Location of your HTML login form components (i.e. “includes”) # in relation to your Voyager cgi-bin directory my $form_dir = "../html/adaptor"; print "Content-type: text/html\n\n"; &PrintInc ("$form_dir/login0.inc"); if ($pid) { &PrintButtons; } &PrintInc ("$form_dir/login1.inc"); if ($pid) { print qq(\t \n); } &PrintInc ("$form_dir/login2.inc");
Michael Doran - University of Texas at Arlington - EndUser Advice for getting started Read the Voyager documentation “WebVoy á ge Patron Authentication Adaptor feature” in the Technical User’s Guide Learn about the authentication system you will be using (e.g. LDAP) The protocol itself – specifically the API How it is implemented at your university Talk to your university’s IT people Look at some example adaptor scripts
Michael Doran - University of Texas at Arlington - EndUser Development & testing Test server is nice but not necessary You can easily develop and test with a WebVoy á ge “preview server” type set up First step should be to write a minimal LDAP client in your chosen programming language You are welcome to modify/adapt UTA’s “login.cgi” adaptor script included as a separate handout
Michael Doran - University of Texas at Arlington - EndUser Questions & (hopefully) answers