LP 1917083: Add SSO support to BPAC
authorJason Boyer <JBoyer@equinoxOLI.org>
Fri, 30 Sep 2022 20:28:51 +0000 (16:28 -0400)
committerJason Boyer <JBoyer@equinoxOLI.org>
Fri, 10 Feb 2023 14:45:43 +0000 (09:45 -0500)
Support SSO login on the login modal and main login page and simplify
sso_org handling a little in EGCatLoader.

Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
Open-ILS/src/templates-bootstrap/opac/parts/login/form.tt2
Open-ILS/src/templates-bootstrap/opac/parts/login/login_fields.tt2 [new file with mode: 0644]
Open-ILS/src/templates-bootstrap/opac/parts/login/login_modal.tt2
Open-ILS/src/templates-bootstrap/opac/parts/topnav_links.tt2

index fab9dd6..8e0ff4e 100644 (file)
@@ -305,7 +305,7 @@ sub redirect_ssl {
 sub redirect_auth {
     my $self = shift;
 
-    my $sso_org = $ENV{sso_loc} || $self->get_physical_loc || $self->_get_search_lib();
+    my $sso_org = $self->ctx->{sso_org};
     my $sso_enabled = $self->ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.enable');
     my $sso_native = $self->ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.allow_native');
 
@@ -322,6 +322,7 @@ sub redirect_auth {
 # -----------------------------------------------------------------------------
 sub load_simple {
     my ($self, $page) = @_;
+
     $self->ctx->{page} = $page;
     $self->ctx->{search_ou} = $self->_get_search_lib();
 
@@ -476,6 +477,8 @@ sub load_common {
     $ctx->{course_ou} = int($self->cgi->param('locg')) || $self->ctx->{physical_loc} || $self->ctx->{aou_tree}->()->id;
     $ctx->{use_courses} = $ctx->{get_org_setting}->($ctx->{course_ou}, 'circ.course_materials_opt_in') ? 1 : 0;
 
+    $ctx->{sso_org} = $ENV{sso_loc} || $ctx->{physical_loc} || $ctx->{search_ou};
+
     return Apache2::Const::OK;
 }
 
@@ -553,8 +556,8 @@ sub load_login {
 
     $self->timelog("Load login begins");
 
-    my $sso_org = $ENV{sso_loc} || $self->get_physical_loc || $self->_get_search_lib();
-    $ctx->{sso_org} = $sso_org;
+    my $sso_org = $ctx->{sso_org};
+
     my $sso_enabled = $ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.enable');
     my $sso_native = $ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.allow_native');
     my $sso_eg_match = $ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.evergreen_matchpoint') || 'usrname';
@@ -569,12 +572,12 @@ sub load_login {
     my $persist = $cgi->param('persist');
     my $client_tz = $cgi->param('client_tz');
 
-    my $sso_user_match_value;
+    my $sso_user_match_value = $ENV{$sso_shib_match};
     my $response;
     my $sso_logged_in;
     $self->timelog("SSO is enabled") if ($sso_enabled);
     if ($sso_enabled
-        and $sso_user_match_value = $ENV{$sso_shib_match}
+        and $sso_user_match_value
         and (!$self->cgi->cookie(COOKIE_SHIB_LOGGEDOUT) or $self->{_ignore_shib_logged_out_cookie})
     ) { # we have a shib session, and have not cleared a previous shib-login cookie
         $self->{_ignore_shib_logged_out_cookie} = 0; # only set by an intermediate call that internally redirected here
@@ -727,10 +730,11 @@ sub load_manual_shib_login {
     my $self = shift;
     my $redirect_to = shift || $self->cgi->param('redirect_to');
 
-    my $sso_org = $ENV{sso_loc} || $self->get_physical_loc || $self->_get_search_lib();
+    my $sso_org = $ctx->{sso_org};
     my $sso_entity_id = $self->ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.entityId');
     my $sso_shib_match = $self->ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.shib_matchpoint') || 'uid';
 
+
     if ($ENV{$sso_shib_match}) {
         $self->{_ignore_shib_logged_out_cookie} = 1;
         return $self->load_login;
@@ -762,8 +766,8 @@ sub load_logout {
         || $self->ctx->{home_page};
     my $active_logout = $self->cgi->param('active_logout');
 
-    my $sso_org = $ENV{sso_loc} || $self->get_physical_loc || $self->_get_search_lib();
-    $self->ctx->{sso_org} = $sso_org;
+    my $sso_org = $self->ctx->{sso_org};
+
     my $sso_enabled = $self->ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.enable');
     my $sso_entity_id = $self->ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.entityId');
     my $sso_logout = $self->ctx->{get_org_setting}->($sso_org, 'opac.login.shib_sso.logout');
index fcd8d87..259f00a 100755 (executable)
@@ -1,9 +1,35 @@
+[%
+
+    redirect = CGI.param('redirect_to');
+    # Don't use referer unless we got here from elsewhere within the TPAC
+    IF !redirect AND ctx.referer.match('^https?://' _ ctx.hostname _ ctx.opac_root);
+        redirect = ctx.referer;
+    END;
 
+    # If no redirect is offered or it's leading us back to the
+    # login form, redirect the user to My Account
+    IF !redirect OR redirect.match(ctx.path_info _ '$');
+        redirect = CGI.url('-full' => 1) _ '/opac/myopac/main';
+    END;
+    redirect = redirect | replace('^http:', 'https:');
+    sso_enabled = ctx.get_org_setting(ctx.sso_org, 'opac.login.shib_sso.enable');
+    sso_native = ctx.get_org_setting(ctx.sso_org, 'opac.login.shib_sso.allow_native');
 
+%]
 <div class='container'>
 <hr>
-    <h3 class="text-center">[% l('Log in to Your Account') %]</h3>
-    <form method='post'>
+    <h3 class="text-center">[% l('Login to Your Account') %]</h3>
+<div class="table table-borderless table-sm">
+
+    [% IF sso_enabled %]
+    [%      final_redirect = redirect | html %]
+    <div id='sso-login-notice'>
+        <button type="submit" class="btn btn-confirm my-2" onclick="window.location = '[% mkurl(ctx.opac_root _ '/manual_shib_login', { redirect_to => final_redirect }) %]'" ><i class="fas fa-sign-in-alt" aria-hidden="true"></i>[% l('Login with SSO') %]</button>
+    [%-      IF sso_native; l(' or use the form below.'); END -%]
+    </div>
+    <br/>
+    [% END %]
+
    <div class="row text-center">[%# INCLUDE "opac/parts/login/help.tt2" %]</div>
     [% IF ctx.login_failed_event %]
 <div id='login-failed-message'>
 %]
 </div>
 [% END %]
+    <form method='post'>
 
-<div class="table table-borderless table-sm">
-       <div class="row">
-               <div class="col-sm w-50">
-                       <label for='username_field' class="lbl1" >[% l('Library Card Number') %]
-                       <a href="#" title="[% INCLUDE "opac/parts/login/username_hint.tt2" %]" data-html="true" data-toggle="tooltip">
-                       <i class="fas fa-question-circle"></i></a></label>
-               </div>
-               <div class="col-sm w-50">
-                       <label for="password_field" class="lbl1" >[% l('PIN') %]
-                       <a href="#" title="[% INCLUDE "opac/parts/login/password_hint.tt2" %]" data-html="true" data-toggle="tooltip">
-            <i class="fas fa-question-circle"></i></a></label>
-               </div>
-       </div>
-       <div class="row">
-               <div class="col-sm w-50">
-                       <input class="form-control" type='text' id="username_field" name="username" autofocus />
-               </div>
-               <div class="col-sm w-50">
-                       <input class="form-control" id="password_field" name="password" type="password"/>
-               </div>
+[% INCLUDE "opac/parts/login/login_fields.tt2"  %]
+<div class="row">
+       <div class="col-sm w-50">
+               <input type="checkbox" value="" id="rememberMe">
+               <label class="form-check-label" for="rememberMe">
+                       [% l('Stay logged in?') %]
+               </label>
        </div>
-       <div class="row">
-               <div class="col-sm w-50">
-                    [% IF ctx.get_org_setting (
-                          ctx.physical_org || ctx.aou_tree.id, 'opac.allow_pending_user') %]
-                       <a href='[% mkurl(ctx.opac_root _ '/register', {}, 1) %]'>[% l('Request A Card') %]</a>
-                    [% END %]
-               </div>
-               <div class="col-sm w-50">
-                       [% IF reset_password == 'true' %]
-                               <a href='[% mkurl(ctx.opac_root _ '/password_reset', {}, 1) %]'>[% l('Forgot Your Password?') %]  </a>
-                       [% END %]
-               </div>
-       </div>
-       <div class="row">
-               <div class="col-sm w-50">
-                       <input type="checkbox" value="" id="rememberMe">
-            <label class="form-check-label" for="rememberMe">
-               [% l('Stay logged in?') %]
-            </label>
-               </div>
-               <div class="col-sm w-50">
-                       <button type="submit" class="btn btn-confirm my-2"><i class="fas fa-sign-in-alt" aria-hidden="true"></i> [% l('Log in') %]</button>
-               </div>
+       <div class="col-sm w-50">
+               <button type="submit" class="btn btn-confirm my-2"><i class="fas fa-sign-in-alt" aria-hidden="true"></i> [% l('Log in') %]</button>
        </div>
 </div>
 
         <div style="clear: both; padding-top: 15px;" class="col-12 text-center">
-        [%
-            redirect = CGI.param('redirect_to');
-            # Don't use referer unless we got here from elsewhere within the TPAC
-            IF !redirect AND ctx.referer.match('^https?://' _ ctx.hostname _ ctx.opac_root);
-                redirect = ctx.referer;
-            END;
-            # If no redirect is offered or it's leading us back to the
-            # login form, redirect the user to My Account
-            IF !redirect OR redirect.match(ctx.path_info _ '$');
-                redirect = CGI.url('-full' => 1) _ '/opac/myopac/main';
-            END;
-                redirect = redirect  | replace('^http:', 'https:');
-            %]
             <input type='hidden' name='redirect_to' value='[% redirect | html %]'/>
-
         </div>
         <input id="client_tz_id" name="client_tz" type="hidden" />
     </form>
 
 </div>
-
diff --git a/Open-ILS/src/templates-bootstrap/opac/parts/login/login_fields.tt2 b/Open-ILS/src/templates-bootstrap/opac/parts/login/login_fields.tt2
new file mode 100644 (file)
index 0000000..7153a93
--- /dev/null
@@ -0,0 +1,36 @@
+    [% IF !sso_enabled || sso_native %]
+    <div class="row">
+        <div class="col-sm w-50">
+            <label for='username_field' class="lbl1" >[% l('Library Card Number') %]
+            <a href="#" title="[% INCLUDE "opac/parts/login/username_hint.tt2" %]" data-html="true" data-toggle="tooltip">
+            <i class="fas fa-question-circle"></i></a></label>
+        </div>
+        <div class="col-sm w-50">
+            <label for="password_field" class="lbl1" >[% l('PIN') %]
+            <a href="#" title="[% INCLUDE "opac/parts/login/password_hint.tt2" %]" data-html="true" data-toggle="tooltip">
+            <i class="fas fa-question-circle"></i></a></label>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-sm w-50">
+            <input class="form-control" type='text' id="username_field" name="username" autofocus />
+        </div>
+        <div class="col-sm w-50">
+            <input class="form-control" id="password_field" name="password" type="password"/>
+        </div>
+    </div>
+    <div class="row">
+        <div class="col-sm w-50">
+                    [% IF ctx.get_org_setting (
+                          ctx.physical_org || ctx.aou_tree.id, 'opac.allow_pending_user') %]
+            <a href='[% mkurl(ctx.opac_root _ '/register', {}, 1) %]'>[% l('Request A Card') %]</a>
+                    [% END %]
+        </div>
+        <div class="col-sm w-50">
+            [% IF reset_password == 'true' %]
+                <a href='[% mkurl(ctx.opac_root _ '/password_reset', {}, 1) %]'>[% l('Forgot Your Password?') %]  </a>
+            [% END %]
+        </div>
+    </div>
+    [% END; # native block %]
+</div>
index a778b7c..015e24a 100755 (executable)
@@ -1,7 +1,26 @@
+[%
+
+    redirect = CGI.param('redirect_to');
+    # Don't use referer unless we got here from elsewhere within the TPAC
+    IF !redirect AND ctx.referer.match('^https?://' _ ctx.hostname _ ctx.opac_root);
+        redirect = ctx.referer;
+    END;
+
+    # If no redirect is offered or it's leading us back to the
+    # login form, redirect the user to My Account
+    IF !redirect OR redirect.match(ctx.path_info _ '$');
+        redirect = CGI.url('-full' => 1) _ '/opac/myopac/main';
+    END;
+    redirect = redirect | replace('^http:', 'https:');
+    sso_enabled = ctx.get_org_setting(ctx.sso_org, 'opac.login.shib_sso.enable');
+    sso_native = ctx.get_org_setting(ctx.sso_org, 'opac.login.shib_sso.allow_native');
+
+
+%]
+
 <div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-hidden="true">
   <div class="modal-dialog modal-dialog-centered" role="document">
     <div class="modal-content">
-     <form method='post' action="/eg/opac/login?redirect_to=%2Feg%2Fopac%2Fmyopac%2Fmain">
       <div class="modal-header">
         <h1 class="modal-title" id="exampleModalLabel">[% l('Login To Evergreen') %]</h1>
         <button type="button" class="close" data-dismiss="modal" aria-label=[% l("Close") %]>
@@ -9,6 +28,14 @@
         </button>
       </div>
       <div class="modal-body">
+    [% IF sso_enabled %]
+    [%      final_redirect = redirect | html %]
+    <div id='sso-login-notice'>
+        <button type="submit" class="btn btn-confirm my-2" onclick="window.location = '[% mkurl(ctx.opac_root _ '/manual_shib_login', { redirect_to => final_redirect }) %]'" ><i class="fas fa-sign-in-alt" aria-hidden="true"></i>[% l('Login with SSO') %]</button>
+    [%-      IF sso_native; l(' or use the form below.'); END -%]
+    </div>
+    <br/>
+    [% END %]
 
       [% IF ctx.login_failed_event %]
     <div id='login-failed-message'>
     </div>
     [% END %]
 
+     <form method='post' action="/eg/opac/login?redirect_to=%2Feg%2Fopac%2Fmyopac%2Fmain">
 <div class='container'>
-       <div class="table table-borderless table-sm">
-               <div class="row">
-                       <div class="col-sm w-50">
-                               <label for='username_field' class="lbl1" >[% l('Library Card Number') %]
-                               <a href="#" title="[% INCLUDE "opac/parts/login/username_hint.tt2" %]" data-html="true" data-toggle="tooltip">
-                               <i class="fas fa-question-circle"></i></a></label>
-                       </div>
-                       <div class="col-sm w-50">
-                               <label for="password_field" class="lbl1" >[% l('PIN') %]
-                               <a href="#" title="[% INCLUDE "opac/parts/login/password_hint.tt2" %]" data-html="true" data-toggle="tooltip">
-                <i class="fas fa-question-circle"></i>
-                </a></label>
-                       </div>
-               </div>
-               <div class="row">
-                       <div class="col-sm w-50">
-                               <input class="form-control" type='text' id="username_field" name="username"/>
-                       </div>
-                       <div class="col-sm w-50">
-                               <input class="form-control" id="password_field" name="password" type="password"/>
-                       </div>
-               </div>
-               <div class="row">
-                       <div class="col-sm w-50">
-                            [% IF ctx.get_org_setting(
-                                ctx.physical_loc || ctx.aou_tree.id, 'opac.allow_pending_user') %]
-                               <a href='[% mkurl(ctx.opac_root _ '/register', {}, 1) %]'>[% l('Request A Card') %]</a>
-                            [% END %]
-                       </div>
-                       <div class="col-sm w-50">
-                               [% IF reset_password == 'true' %]
-                               <a href='[% mkurl(ctx.opac_root _ '/password_reset', {}, 1) %]'>[% l('Forgot Your Password?') %]  </a>
-                               [% END %]
-                       </div>
-               </div>
-       </div>
-
-    <div class="mx-auto row py-4">
+[% INCLUDE "opac/parts/login/login_fields.tt2"  %]
+    <div class="mx-auto row">
 
         <div style="clear: both; padding-top: 15px;" class="col-12">
-        [%
-            redirect = CGI.param('redirect_to');
-            # Don't use referer unless we got here from elsewhere within the TPAC
-            IF !redirect AND ctx.referer.match('^https?://' _ ctx.hostname _ ctx.opac_root);
-                redirect = ctx.referer;
-            END;
-            # If no redirect is offered or it's leading us back to the
-            # login form, redirect the user to My Account
-            IF !redirect OR redirect.match(ctx.path_info _ '$');
-                redirect = CGI.url('-full' => 1) _ '/opac/myopac/main';
-            END;
-                redirect = redirect  | replace('^http:', 'https:');
-            %]
         </div>
 
         <input id="client_tz_id" name="client_tz" type="hidden" />
@@ -86,7 +65,6 @@
   </div>
     [%# INCLUDE "opac/parts/login/help.tt2" %]
 
-      </div>
       <div class="modal-footer">
       <div class="mr-auto">
         <input type='hidden' name='redirect_to' value='[% redirect | html %]'/>
index 63b2291..a13d92f 100755 (executable)
@@ -65,7 +65,7 @@
         </li>
         <!--Logout-->
         <li class="nav-item">
-        <a class="nav-link" href="[% mkurl(ctx.opac_root _ '/logout', {}, 1) %]" id="logout_link">[% l('Logout') %]</a>
+        <a class="nav-link" href="[% mkurl(ctx.opac_root _ '/logout', {active_logout => 1}, 1) %]" id="logout_link">[% l('Logout') %]</a>
         </li>
       [% END %]
       <!--must end ul and div no matter the user state-->