From: Art Rhyno Date: Fri, 8 Mar 2013 12:55:06 +0000 (-0500) Subject: Fix CAS to handle dynamic auth links X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=b3e62feaad82600b262bcbc750f3b40f5a7bf2c9;p=contrib%2FConifer.git Fix CAS to handle dynamic auth links CAS uses a "service" URL to redirect a user back to where an application wants them to go if authentication is passed. This works well for simple URLs but becomes problematic for complex URLs, which can get mangled or, worse, truncated. This doesn't seem to be unique to Windsor's implmentation of CAS. I tried a few tricks to encode the URLs in strange ways to get the same URL back from CAS, but I think a better approach is to stuff the URL into a cookie, and invoke when the request comes back from CAS. Any other approach seems to result in horrid URLs and there is always the chance that some character will break the scheme. One flaw in my approach is that if a TPAC user selects "email" or "place hold" and invokes the logon screen, the cookie gets set for the "redirect" URL. If, for some reason, a user decides to do another search and chooses to log in to their account from a different screen, the CAS URL can be invoked. This would only happen for CAS, and the cookie itself is only set for 10 minutes, so I don't think this is a major concession. I also try to invalidate the cookie wherever it is possible to know that the authentication has not been invoked. The assumption is that there is a CAS link added to the login form (login/form.tt2), for example: [% l('Log in to Your Account (UWind ID)') %] I had become so used to testing CAS by logging in first, that I totally missed the links that support authentication at the time of need, e.g. the "email" or "place hold" links that are displayed prior to authentication. Hopefully, this branch will address what is probably a common scenario. Signed-off-by: Art Rhyno Conflicts: Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm index 0838a29eb5..77b1543da5 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm @@ -28,6 +28,8 @@ my $U = 'OpenILS::Application::AppUtils'; use constant COOKIE_SES => 'ses'; use constant COOKIE_LOGGEDIN => 'eg_loggedin'; +use constant COOKIE_LOGGEDIN_CAS => 'eg_CAS'; +use constant COOKIE_URL_CAS => 'eg_CAS_URL'; use constant COOKIE_PHYSICAL_LOC => 'eg_physical_loc'; use constant COOKIE_SSS_EXPAND => 'eg_sss_expand'; @@ -359,6 +361,41 @@ sub load_login { my $persist = $cgi->param('persist'); # initial log form only + my $ticket = $cgi->param('ticket'); + my $cas_redirect_to = $cgi->param('redirect_to'); + if ($cgi->cookie(COOKIE_URL_CAS)) { + $cas_redirect_to = $cgi->cookie(COOKIE_URL_CAS); + } + my $cas_flag = '0'; + + # initial log form only + if ($ticket) { + # CAS does not have either username or password at this point, so we fudge these + # values for the other checks + $username = '_CAS_'; + $password = '_CAS_'; + + } + + my $login_page = sprintf('%s://%s%s/login',($self->ctx->{is_staff} ? 'oils' : 'https'), $self->ctx->{hostname}, $self->ctx->{opac_root}); + + # CAS does not handle complex URLs, so we put the URL in a cookie + if (!$cgi->cookie(COOKIE_URL_CAS) && $cas_redirect_to && !$username && !$password) { + return $self->generic_redirect( + "$login_page?redirect_to=$cas_redirect_to", + [ + # contains the service url for CAS + $cgi->cookie( + -name => COOKIE_URL_CAS, + -path => '/', + -secure => 0, + -value => $cas_redirect_to, + -expires => '+10m' + ) + ] + ); + } + return Apache2::Const::OK unless $username and $password; my $auth_proxy_enabled = 0; # default false @@ -397,6 +434,13 @@ sub load_login { 'open-ils.auth', 'open-ils.auth.authenticate.complete', $args); } else { $args->{password} = $password; + if ($ticket) { + $args->{ticket} = $ticket; + $cas_flag = '1'; + } else { + # zap CAS redirect if not CAS request + $cas_redirect_to = undef; + } $response = $U->simplereq( 'open-ils.auth_proxy', 'open-ils.auth_proxy.login', $args); @@ -418,6 +462,7 @@ sub load_login { my $login_cookie_expires = ($persist) ? CORE::time + $response->{payload}->{authtime} : undef; return $self->generic_redirect( + $cas_redirect_to || $cgi->param('redirect_to') || $acct, [ # contains the actual auth token and should be sent only over https @@ -436,6 +481,22 @@ sub load_login { -secure => 0, -value => '1', -expires => $login_cookie_expires + ), + # invalidate CAS url since it is only needed at point of authentication + # if it is used, have it go to login page + $cgi->cookie( + -name => COOKIE_URL_CAS, + -path => '/', + -value => $login_page, + -expires => '-1h' + ), + # contains only a hint that we are using CAS + $cgi->cookie( + -name => COOKIE_LOGGEDIN_CAS, + -path => '/', + -secure => 0, + -value => $cas_flag, + -expires => $login_cookie_expires ) ] ); @@ -448,6 +509,9 @@ sub load_logout { my $self = shift; my $redirect_to = shift || $self->cgi->param('redirect_to'); + my $login_page = sprintf('%s://%s%s/login',($self->ctx->{is_staff} ? 'oils' : 'https'), + $self->ctx->{hostname}, $self->ctx->{opac_root}); + # If the user was adding anyting to an anonymous cache # while logged in, go ahead and clear it out. $self->clear_anon_cache; @@ -467,6 +531,18 @@ sub load_logout { -path => '/', -value => '', -expires => '-1h' + ), + $self->cgi->cookie( + -name => COOKIE_URL_CAS, + -path => '/', + -value => $login_page, + -expires => '-1h' + ), + $self->cgi->cookie( + -name => COOKIE_LOGGEDIN_CAS, + -path => '/', + -value => '', + -expires => '-1h' ) ] );