--- loncom/auth/lonshibauth.pm 2021/11/03 01:04:02 1.12
+++ loncom/auth/lonshibauth.pm 2021/12/12 20:56:36 1.14.2.1
@@ -1,7 +1,8 @@
# The LearningOnline Network
-# Redirect Shibboleth authentication to designated URL (/adm/sso).
+# Redirect Single Sign On authentication to designated URL:
+# /adm/sso, by default.
#
-# $Id: lonshibauth.pm,v 1.12 2021/11/03 01:04:02 raeburn Exp $
+# $Id: lonshibauth.pm,v 1.14.2.1 2021/12/12 20:56:36 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -28,14 +29,15 @@
=head1 NAME
-Apache::lonshibauth - Redirect Shibboleth authentication
+Apache::lonshibauth - Redirect Single Sign On authentication
=head1 SYNOPSIS
-Invoked when lonOtherAuthen is set to yes, and type is Shibboleth
+Invoked when an Apache config file includes:
+PerlAuthenHandler Apache::lonshibauth
If server is configured as a Shibboleth SP, the main Apache
-configuration file, e.g., /etc/httpd/conf/httpd.conf
+configuration file, e.g., /etc/httpd/conf/httpd.conf
(for RHEL/CentOS/Scentific Linux/Fedora) should contain:
LoadModule mod_shib /usr/lib/shibboleth/mod_shib_22.so
@@ -43,10 +45,99 @@ LoadModule mod_shib /usr/lib/shibboleth/
or equivalent (depending on Apache version)
before the line to include conf/loncapa_apache.conf
+If some other Apache module is in use for Single Sign On
+authentication e.g., mod_auth_cas or mod_sentinel,
+then a separate config file should be created which
+includes settings for the authentication module.
+
=head1 INTRODUCTION
-Redirects a user requiring Single Sign On via Shibboleth to a
-URL -- /adm/sso -- on the server which is configured to use that service.
+Redirects a user requiring Single Sign On to a URL on the server
+which is configured to use that service. The default URL is:
+/adm/sso.
+
+If this is to be used with a Single Sign On service other Shibboleth
+then an Apache config file needs to be loaded which:
+
+(a) loads the corresponding Apache module, and
+(b) sets appropriate values for perl vars in
+an block, and
+(c) sets an appropriate value for AuthType in a
+
+ block, which also contains
+
+require valid-user
+
+PerlAuthzHandler Apache::lonshibacc
+
+PerlAuthzHandler Apache::lonacc
+
+In the case of Shibboleth no additional file is needed
+because loncapa_apache.conf already contains:
+
+
+ PerlAuthenHandler Apache::lonshibauth
+ PerlSetVar lonOtherAuthen yes
+ PerlSetVar lonOtherAuthenType Shibboleth
+
+
+
+and
+
+
+ Header set Cache-Control "private,no-store,no-cache,max-age=0"
+
+ AuthType shibboleth
+ ShibUseEnvironment On
+ ShibRequestSetting requireSession 1
+ ShibRequestSetting redirectToSSL 443
+ require valid-user
+ PerlAuthzHandler Apache::lonshibacc
+ PerlAuthzHandler Apache::lonacc
+ ErrorDocument 403 /adm/login
+ ErrorDocument 500 /adm/errorhandler
+
+
+ PerlTypeHandler Apache::lonnoshib
+
+
+
+
+If the service is not Shibboleth, then (optionally) a URL that is
+not /adm/sso can be used as the URL for the service, e.g., /adm/cas
+or /adm/sentinel, by setting a lonOtherAuthenUrl perl var
+in an Apache config file containing (for example):
+
+PerlSetVar lonOtherAuthenUrl /adm/sentinel
+
+
+ PerlAuthenHandler Apache::lonshibauth
+ PerlSetVar lonOtherAuthen yes
+ PerlSetVar lonOtherAuthenType Sentinel
+
+
+
+
+ Header set Cache-Control "private,no-store,no-cache,max-age=0"
+
+ AuthType Sentinel
+ require valid-user
+ PerlAuthzHandler Apache::lonshibacc
+ PerlAuthzHandler Apache::lonacc
+ ErrorDocument 403 /adm/login
+ ErrorDocument 500 /adm/errorhandler
+
+
+ PerlTypeHandler Apache::lonnoshib
+
+
+
+
+In the example above for Sentinel SSO, it would also be possible to
+use /adm/sso instead of /adm/sentinel, in which case (i) there would be
+no need to define lonOtherAuthenUrl, (ii) there would be
+and (iii) the block would not be needed as
+it is already present in /etc/httpd/conf/loncapa_apache.conf.
=head1 HANDLER SUBROUTINE
@@ -54,10 +145,56 @@ This routine is called by Apache and mod
=over 4
-If $r->user defined and requested uri not /adm/sso
-redirect to /adm/sso
+If $r->user is defined and requested URL is not /adm/sso or
+other specific URL as set by a lonOtherAuthenUrl perlvar,
+then redirect to /adm/sso (or to the specific URL).
+
+Otherwise return DECLINED.
+
+In the case of redirection a query string is appended,
+which will contain either (a) the originally requested URL,
+if not /adm/sso (or lonOtherAuthenUrl URL), and
+any existing query string in the original request, or
+(b) if redirect is to /adm/login to support dual SSO and
+non-SSO, a query string which contains sso=tokenID, where the
+token contains information for deep-linking to course/resource.
+
+Support is included for use of LON-CAPA's standard log-in
+page -- /adm/login -- to support dual SSO and non-SSO
+authentication from that "landing" page.
+
+To enable dual SSO and non-SSO access from /adm/login
+a Domain Coordinator will use the web GUI:
+Main Menu > Set domain configuration > Display
+("Log-in page options" checked)
+and for any of the LON-CAPA domain's servers which
+will offer dual login will check "Yes" and then set:
+(a) SSO Text, Image, Alt Text, URL, Tool Tip
+(b) non-SSO: Text
+
+The value in the URL field should be /adm/sso,
+or the same URL as set for the lonOtherAuthenUrl
+perl var, e.g., /adm/sentinel.
-Otherwise return DECLINED
+=back
+
+=head1 NOTABLE SUBROUTINES
+
+=over 4
+
+=item set_token()
+
+Inputs: 2
+$r - request object
+$lonhost - hostID of current server
+
+Output: 1
+$querystring - query string to append to URL
+when redirecting.
+
+If role and/or symb are present in the original query string:
+then they will be stored in the token file on the server,
+for access later to support deep-linking.
=back
@@ -75,11 +212,15 @@ use LONCAPA qw(:DEFAULT :match);
sub handler {
my $r = shift;
- my $target = '/adm/sso';
+ my $ssourl = '/adm/sso';
+ if ($r->dir_config('lonOtherAuthenUrl') ne '') {
+ $ssourl = $r->dir_config('lonOtherAuthenUrl');
+ }
+ my $target = $ssourl;
if (&Apache::lonnet::get_saml_landing()) {
$target = '/adm/login';
}
- if (($r->user eq '') && ($r->uri ne $target) && ($r->uri ne '/adm/sso')) {
+ if (($r->user eq '') && ($r->uri ne $target) && ($r->uri ne $ssourl)) {
my $lonhost = $Apache::lonnet::perlvar{'lonHostID'};
my $hostname = &Apache::lonnet::hostname($lonhost);
if (!$hostname) { $hostname = $r->hostname(); }
@@ -87,7 +228,7 @@ sub handler {
unless ($protocol eq 'https') { $protocol = 'http'; }
my $alias = &Apache::lonnet::use_proxy_alias($r,$lonhost);
if (($alias ne '') &&
- (&Apache::lonnet::alias_shibboleth($lonhost))) {
+ (&Apache::lonnet::alias_sso($lonhost))) {
$hostname = $alias;
}
my $dest = $protocol.'://'.$hostname.$target;
@@ -98,19 +239,12 @@ sub handler {
}
} else {
my $uri = $r->uri;
- if ($uri =~ m{^/tiny/$match_domain/\w+$}) {
- my $querystring = &set_token($r,$lonhost);
- if ($querystring ne '') {
- $dest .= '?'.$querystring;
- }
- } else {
- if ($r->args ne '') {
- $dest .= (($dest=~/\?/)?'&':'?').$r->args;
- }
- unless (($uri eq '/adm/roles') || ($uri eq '/adm/logout')) {
- unless ($r->args =~ /origurl=/) {
- $dest.=(($dest=~/\?/)?'&':'?').'origurl='.$uri;
- }
+ if ($r->args ne '') {
+ $dest .= (($dest=~/\?/)?'&':'?').$r->args;
+ }
+ unless (($uri eq '/adm/roles') || ($uri eq '/adm/logout')) {
+ unless ($r->args =~ /origurl=/) {
+ $dest.=(($dest=~/\?/)?'&':'?').'origurl='.$uri;
}
}
}
@@ -124,7 +258,7 @@ sub handler {
sub set_token {
my ($r,$lonhost) = @_;
my ($firsturl,$querystring,$ssotoken,@names,%token);
- @names = ('role','symb','ltoken','linkkey');
+ @names = ('role','symb');
map { $token{$_} = 1; } @names;
unless (($r->uri eq '/adm/roles') || ($r->uri eq '/adm/logout')) {
$firsturl = $r->uri;
@@ -132,34 +266,10 @@ sub set_token {
if ($r->args ne '') {
&Apache::loncommon::get_unprocessed_cgi($r->args);
}
- if ($r->uri =~ m{^/tiny/$match_domain/\w+$}) {
- if ($env{'form.ttoken'}) {
- my %info = &Apache::lonnet::tmpget($env{'form.ttoken'});
- &Apache::lonnet::tmpdel($env{'form.ttoken'});
- if ($info{'ltoken'}) {
- $env{'form.ltoken'} = $info{'ltoken'};
- } elsif ($info{'linkkey'} ne '') {
- $env{'form.linkkey'} = $info{'linkkey'};
- }
- } else {
- unless (($env{'form.ltoken'}) || ($env{'form.linkkey'})) {
- &Apache::lonacc::get_posted_cgi($r,['linkkey']);
- }
- }
- }
my $extras;
foreach my $name (@names) {
if ($env{'form.'.$name} ne '') {
- if ($name eq 'ltoken') {
- my %info = &Apache::lonnet::tmpget($env{'form.ltoken'});
- &Apache::lonnet::tmpdel($env{'form.ltoken'});
- if ($info{'linkprot'}) {
- $extras .= '&linkprot='.&escape($info{'linkprot'});
- last;
- }
- } else {
- $extras .= '&'.$name.'='.&escape($env{'form.'.$name});
- }
+ $extras .= '&'.$name.'='.&escape($env{'form.'.$name});
}
}
if (($firsturl ne '') || ($extras ne '')) {
@@ -172,7 +282,7 @@ sub set_token {
foreach my $key (sort(keys(%env))) {
if ($key =~ /^form\.(.+)$/) {
my $name = $1;
- next if (($token{$name}) || ($name eq 'ttoken'));
+ next if ($token{$name});
$querystring .= '&'.$name.'='.$env{$key};
}
}