[LON-CAPA-cvs] cvs: doc /loncapafiles loncapafiles.lpml loncom loncapa_apache.conf lontrans.pm loncom/auth lonacc.pm lonauth.pm lonlogin.pm lonrelaunch.pm lonshibauth.pm migrateuser.pm switchserver.pm loncom/lti ltiauth.pm
raeburn
raeburn at source.lon-capa.org
Fri Jun 17 22:10:20 EDT 2022
raeburn Sat Jun 18 02:10:20 2022 EDT
Added files:
/loncom/auth lonrelaunch.pm
Modified files:
/loncom/auth lonacc.pm lonauth.pm lonlogin.pm lonshibauth.pm
migrateuser.pm switchserver.pm
/loncom/lti ltiauth.pm
/loncom lontrans.pm loncapa_apache.conf
/doc/loncapafiles loncapafiles.lpml
Log:
- Bug 6907
For LTI-protected deep links in which username is included in launch payload
compare username in payload with username for any existing LON-CAPA session
in current web browser and expire old session, if different user.
-------------- next part --------------
Index: loncom/auth/lonacc.pm
diff -u loncom/auth/lonacc.pm:1.202 loncom/auth/lonacc.pm:1.203
--- loncom/auth/lonacc.pm:1.202 Tue Dec 7 23:19:00 2021
+++ loncom/auth/lonacc.pm Sat Jun 18 02:10:18 2022
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Cookie Based Access Handler
#
-# $Id: lonacc.pm,v 1.202 2021/12/07 23:19:00 raeburn Exp $
+# $Id: lonacc.pm,v 1.203 2022/06/18 02:10:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -281,10 +281,18 @@
be identified by the third arg ($usename), except when lonacc is called in
an internal redirect to /adm/switchserver (e.g., load-balancing following
successful authentication) -- no cookie set yet. For that particular case
- simply skip the call to sso_login().
+ simply skip the call to sso_login().
returns OK if it was SSO and user was handled.
returns undef if not SSO or no means to handle the user.
+
+ In the case where the session was started from /adm/launch/tiny/$domain/$id,
+ i.e., for a protected link, with launch from another CMS, and user information
+ is accepted from the LTI payload, then, if the user has privileged roles,
+ authentication will be required. If SSO authentication is with a username
+ and/or domain that differ from the username in the LTI payload and domain
+ in the launch URL, then $r->user() will be unset and /adm/relaunch will be
+ called.
=cut
@@ -325,7 +333,7 @@
}
}
- my ($linkprot,$linkkey);
+ my ($linkprot,$linkprotuser,$linkkey,$deeplinkurl);
#
# If Shibboleth auth is in use, and a dual SSO and non-SSO login page
@@ -357,9 +365,13 @@
&Apache::lonnet::tmpdel($form{'ttoken'});
if ($info{'origurl'}) {
$form{'origurl'} = $info{'origurl'};
+ if ($form{'origurl'} =~ m{^/tiny/$match_domain/\w+$}) {
+ $deeplinkurl = $form{'origurl'};
+ }
}
if ($info{'linkprot'}) {
$linkprot = $info{'linkprot'};
+ $linkprotuser = $info{'linkprotuser'};
} elsif ($info{'linkkey'} ne '') {
$linkkey = $info{'linkkey'};
}
@@ -380,9 +392,11 @@
}
if ($firsturl =~ m{^/tiny/$match_domain/\w+$}) {
$form{'origurl'} = $firsturl;
+ $deeplinkurl = $firsturl;
}
if ($form{'linkprot'}) {
$linkprot = $form{'linkprot'};
+ $linkprotuser = $form{'linkprotuser'};
} elsif ($form{'linkkey'} ne '') {
$linkkey = $form{'linkkey'};
}
@@ -400,6 +414,9 @@
my ($firsturl, at rest)=split(/\&/,$info);
if ($firsturl ne '') {
$form{'origurl'} = &unescape($firsturl);
+ if ($form{'origurl'} =~ m{^/tiny/$match_domain/\w+$}) {
+ $deeplinkurl = $form{'origurl'};
+ }
}
foreach my $item (@rest) {
my ($key,$value) = split(/=/,$item);
@@ -407,6 +424,7 @@
}
if ($form{'linkprot'}) {
$linkprot = $form{'linkprot'};
+ $linkprotuser = $form{'linkprotuser'};
} elsif ($form{'linkkey'} ne '') {
$linkkey = $form{'linkkey'};
}
@@ -414,8 +432,14 @@
} elsif ($form{'ltoken'}) {
my %link_info = &Apache::lonnet::tmpget($form{'ltoken'});
$linkprot = $link_info{'linkprot'};
+ if (($linkprot) && ($link_info{'linkprotuser'} ne '')) {
+ $linkprotuser = $link_info{'linkprotuser'};
+ }
my $delete = &Apache::lonnet::tmpdel($form{'ltoken'});
delete($form{'ltoken'});
+ if ($form{'origurl'} =~ m{^/tiny/$match_domain/\w+$}) {
+ $deeplinkurl = $form{'origurl'};
+ }
} elsif ($form{'linkkey'} ne '') {
$linkkey = $form{'linkkey'};
}
@@ -424,6 +448,23 @@
if ($domain eq '') {
$domain = $r->dir_config('lonDefDomain');
}
+ if (($deeplinkurl) && ($linkprot) && ($linkprotuser ne '')) {
+ unless ($linkprotuser eq $user.':'.$domain) {
+ $r->user();
+ my %data = (
+ origurl => $deeplinkurl,
+ linkprot => $linkprot,
+ linkprotuser => $linkprotuser,
+ );
+ my $token = &Apache::lonnet::tmpput(\%data,$r->dir_config('lonHostID'),'link');
+ unless (($token eq 'con_lost') || ($token eq 'refused') || ($token =~ /^error:/) ||
+ ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {
+ $r->internal_redirect('/adm/relaunch?rtoken='.$token);
+ $r->set_handlers('PerlHandler'=> undef);
+ return OK;
+ }
+ }
+ }
my $home=&Apache::lonnet::homeserver($user,$domain);
if ($home !~ /(con_lost|no_host|no_such_host)/) {
&Apache::lonnet::logthis(" SSO authorized user $user ");
@@ -477,6 +518,9 @@
if ($env{'request.deeplink.login'}) {
if ($linkprot) {
$env{'request.linkprot'} = $linkprot;
+ if ($linkprotuser ne '') {
+ $env{'request.linkprotuser'} = $linkprotuser;
+ }
} elsif ($linkkey ne '') {
$env{'request.linkkey'} = $linkkey;
}
@@ -536,9 +580,7 @@
if (($is_balancer) && ($hosthere)) {
$info{'noloadbalance'} = $hosthere;
}
- my $token =
- &Apache::lonnet::tmpput(\%info,
- $r->dir_config('lonHostID'));
+ my $token = &Apache::lonnet::tmpput(\%info,$r->dir_config('lonHostID'),'sso');
$env{'form.token'} = $token;
$r->internal_redirect('/adm/migrateuser');
$r->set_handlers('PerlHandler'=> undef);
@@ -731,13 +773,36 @@
}
}
if ($requrl=~m{^/+tiny/+$match_domain/+\w+$}) {
+ if ($r->args) {
+ &Apache::loncommon::get_unprocessed_cgi($r->args,['ttoken']);
+ if (defined($env{'form.ttoken'})) {
+ my %info = &Apache::lonnet::tmpget($env{'form.ttoken'});
+ if (($info{'linkprotuser'} ne '') && ($info{'origurl'} ne '')) {
+ if (($info{'linkprot'}) && ($info{'origurl'} eq $requrl) &&
+ ($info{'linkprotuser'} ne $env{'user.name'}.':'.$env{'user.domain'})) {
+ my %data = (
+ origurl => $requrl,
+ linkprot => $info{'linkprot'},
+ linkprotuser => $info{'linkprotuser'},
+ );
+ my $token =
+ &Apache::lonnet::tmpput(\%data,$r->dir_config('lonHostID'),'retry');
+ unless (($token eq 'con_lost') || ($token eq 'refused') || ($token =~ /^error:/) ||
+ ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {
+ $r->internal_redirect('/adm/relaunch?rtoken='.$token);
+ $r->set_handlers('PerlHandler'=> undef);
+ return OK;
+ }
+ }
+ }
+ }
+ }
if ($env{'user.name'} eq 'public' &&
$env{'user.domain'} eq 'public') {
$env{'request.firsturl'}=$requrl;
return FORBIDDEN;
- } else {
- return OK;
}
+ return OK;
}
# ---------------------------------------------------------------- Check access
my $now = time;
Index: loncom/auth/lonauth.pm
diff -u loncom/auth/lonauth.pm:1.173 loncom/auth/lonauth.pm:1.174
--- loncom/auth/lonauth.pm:1.173 Sat May 21 05:16:43 2022
+++ loncom/auth/lonauth.pm Sat Jun 18 02:10:18 2022
@@ -1,7 +1,7 @@
# The LearningOnline Network
# User Authentication Module
#
-# $Id: lonauth.pm,v 1.173 2022/05/21 05:16:43 raeburn Exp $
+# $Id: lonauth.pm,v 1.174 2022/06/18 02:10:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -308,6 +308,11 @@
if ($clientunicode && !$clientmathml) {
$args = {'browser.unicode' => 1};
}
+ if ($form->{firsturl} =~ m{^/tiny/$match_domain/\w+$}) {
+ if ($form->{linkprot}) {
+ $args->{only_body} = 1;
+ }
+ }
my @actions;
my $start_page = &Apache::loncommon::start_page('Unsuccessful Login',undef,$args);
@@ -357,7 +362,13 @@
}
}
if (exists($form->{linkprot})) {
- my $ltoken = &Apache::lonnet::tmpput({linkprot => $form->{'linkprot'}},
+ my %info = (
+ 'linkprot' => $form->{'linkprot'},
+ );
+ if ($form->{linkprotuser} ne '') {
+ $info{'linkprotuser'} = $form->{linkprotuser};
+ }
+ my $ltoken = &Apache::lonnet::tmpput(\%info,
$r->dir_config('lonHostID'),'retry');
if ($ltoken) {
$retry .= (($retry =~ /\?/) ? '&' : '?').'ltoken='.$ltoken;
@@ -475,6 +486,19 @@
.$end_page);
} else {
if (($info{'linkprot'}) || ($info{'linkkey'} ne '')) {
+ if (($info{'linkprot'}) && ($info{'linkprotuser'} ne '')) {
+ unless ($info{'linkprotuser'} eq $env{'user.name'}.':'.$env{'user.domain'}) {
+ $r->print(
+ $start_page
+ .'<p class="LC_warning">'.&mt('You are already logged in, but as a different user from the one expected for the link you followed from another system').'</p>'
+ .'<p>'.&mt('Please [_1]log out[_2] first, and then try following the link again from the other system',
+ '<a href="/adm/logout">','</a>')
+
+ .'</p>'
+ .$end_page);
+ return OK;
+ }
+ }
my $token = &Apache::lonnet::tmpput(\%info,$r->dir_config('lonHostID'),'link');
unless (($token eq 'con_lost') || ($token eq 'refused') ||
($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {
@@ -730,6 +754,18 @@
}
}
+ if ($form{'firsturl'} =~ m{^/tiny/$match_domain/\w+$}) {
+ if (($form{'linkprot'}) && ($form{'linkprotuser'} ne '')) {
+ unless($form{'linkprotuser'} eq $form{'uname'}.':'.$form{'udom'}) {
+ delete($form{'udom'});
+ delete($form{'uname'});
+ &failed($r,'Username and/or domain are different to that expected for the link you followed from another system',
+ \%form,$authhost);
+ return OK;
+ }
+ }
+ }
+
my ($is_balancer,$otherserver);
unless ($hosthere) {
@@ -975,7 +1011,7 @@
my ($form,$lonhost,$querystr) = @_;
if (ref($form) eq 'HASH') {
my ($firsturl,$token,$extras, at names);
- @names = ('role','symb','linkprot','linkkey','iptoken');
+ @names = ('role','symb','linkprotuser','linkprot','linkkey','iptoken');
foreach my $name (@names) {
if ($form->{$name} ne '') {
$extras .= '&'.$name.'='.&escape($form->{$name});
Index: loncom/auth/lonlogin.pm
diff -u loncom/auth/lonlogin.pm:1.198 loncom/auth/lonlogin.pm:1.199
--- loncom/auth/lonlogin.pm:1.198 Wed Jun 1 12:12:32 2022
+++ loncom/auth/lonlogin.pm Sat Jun 18 02:10:18 2022
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Login Screen
#
-# $Id: lonlogin.pm,v 1.198 2022/06/01 12:12:32 raeburn Exp $
+# $Id: lonlogin.pm,v 1.199 2022/06/18 02:10:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -68,6 +68,9 @@
$env{'form.ltoken'} = $info{'ltoken'};
} elsif ($info{'linkprot'}) {
$env{'form.linkprot'} = $info{'linkprot'};
+ if ($info{'linkprotuser'} ne '') {
+ $env{'form.linkprotuser'} = $info{'linkprotuser'};
+ }
} elsif ($info{'linkkey'} ne '') {
$env{'form.linkkey'} = $info{'linkkey'};
}
@@ -181,6 +184,9 @@
$link_info{'ltoken'} = $env{'form.ltoken'};
} elsif ($env{'form.linkprot'}) {
$link_info{'linkprot'} = $env{'form.linkprot'};
+ if ($env{'form.linkprotuser'} ne '') {
+ $link_info{'linkprotuser'} = $env{'form.linkprotuser'};
+ }
} elsif ($env{'form.linkkey'} ne '') {
$link_info{'linkkey'} = $env{'form.linkkey'};
}
@@ -249,16 +255,31 @@
$dest = &HTML::Entities::encode($env{'form.firsturl'},'\'"<>&');
}
if (($env{'form.ltoken'}) || ($env{'form.linkprot'})) {
- my $linkprot;
+ my ($linkprot,$linkprotuser);
if ($env{'form.ltoken'}) {
my %info = &Apache::lonnet::tmpget($env{'form.ltoken'});
$linkprot = $info{'linkprot'};
+ if ($info{'linkprotuser'} ne '') {
+ $linkprotuser = $info{'linkprotuser'};
+ }
my $delete = &Apache::lonnet::tmpdel($env{'form.ltoken'});
} else {
$linkprot = $env{'form.linkprot'};
+ $linkprotuser = $env{'form.linkprotuser'};
}
if ($linkprot) {
my ($linkprotector,$deeplink) = split(/:/,$linkprot,2);
+ if (($deeplink =~ m{^/tiny/$match_domain/\w+$}) &&
+ ($linkprotuser ne '') && ($linkprotuser ne $env{'user.name'}.':'.$env{'user.domain'})) {
+ my $ip = &Apache::lonnet::get_requestor_ip();
+ my %linkprotinfo = (
+ origurl => $deeplink,
+ linkprot => $linkprot,
+ linkprotuser => $linkprotuser,
+ );
+ &Apache::migrateuser::logout($r,$ip,$handle,undef,undef,\%linkprotinfo);
+ return OK;
+ }
if ($env{'user.linkprotector'}) {
my @protectors = split(/,/,$env{'user.linkprotector'});
unless (grep(/^\Q$linkprotector\E$/, at protectors)) {
@@ -429,7 +450,7 @@
# -------------------------------------------------------- Store away log token
my ($tokenextras,$tokentype,$linkprot_for_login);
- my @names = ('role','symb','iptoken','ltoken','linkprot','linkkey');
+ my @names = ('role','symb','iptoken','ltoken','linkprotuser','linkprot','linkkey');
foreach my $name (@names) {
if ($env{'form.'.$name} ne '') {
if ($name eq 'ltoken') {
@@ -437,6 +458,9 @@
if ($info{'linkprot'}) {
$linkprot_for_login = $info{'linkprot'};
$tokenextras .= '&linkprot='.&escape($info{'linkprot'});
+ if ($info{'linkprotuser'}) {
+ $tokenextras .= '&linkprotuser='.&escape($info{'linkprotuser'});
+ }
$tokentype = 'link';
last;
}
@@ -1125,28 +1149,52 @@
$path = '/'.$path;
}
my $url = $protocol.'://'.$hostname.$path;
- if ($env{'form.firsturl'} ne '') {
+ if ($env{'form.firsturl'} =~ m{^/tiny/$match_domain/\w+$}) {
+ $url = $protocol.'://'.$hostname.$env{'form.firsturl'};
+ if (($env{'form.ltoken'}) || ($env{'form.linkprot'} ne '') ||
+ ($env{'form.linkkey'} ne '')) {
+ my %link_info;
+ if ($env{'form.ltoken'}) {
+ %link_info = &Apache::lonnet::tmpget($env{'form.ltoken'});
+ &Apache::lonnet::tmpdel($env{'form.ltoken'});
+ } elsif ($env{'form.linkprot'}) {
+ $link_info{'linkprot'} = $env{'form.linkprot'};
+ if ($env{'form.linkprotuser'}) {
+ $link_info{'linkprotuser'} = $env{'form.linkprotuser'};
+ }
+ } elsif ($env{'form.linkkey'} ne '') {
+ $link_info{'linkkey'} = $env{'form.linkkey'};
+ }
+ my $token = &Apache::lonnet::tmpput(\%link_info,$desthost,'link');
+ unless (($token eq 'con_lost') || ($token eq 'refused') ||
+ ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {
+ $url .= '?ltoken='.$token;
+ }
+ }
+ } else {
my $querystring;
- if ($env{'form.firsturl'} =~ /[^\x00-\xFF]/) {
- $querystring = &uri_escape_utf8($env{'form.firsturl'});
- } else {
- $querystring = &uri_escape($env{'form.firsturl'});
+ if ($env{'form.firsturl'} ne '') {
+ if ($env{'form.firsturl'} =~ /[^\x00-\xFF]/) {
+ $querystring = &uri_escape_utf8($env{'form.firsturl'});
+ } else {
+ $querystring = &uri_escape($env{'form.firsturl'});
+ }
+ $querystring = &HTML::Entities::encode($querystring,"'");
+ $querystring = '?firsturl='.$querystring;
}
- $querystring = &HTML::Entities::encode($querystring,"'");
- $url .='?firsturl='.$querystring;
- }
- if (($env{'form.ltoken'}) || ($env{'form.linkkey'} ne '')) {
- my %link_info;
if ($env{'form.ltoken'}) {
- $link_info{'ltoken'} = $env{'form.ltoken'};
- } elsif ($env{'form.linkkey'} ne '') {
- $link_info{'linkkey'} = $env{'form.linkkey'};
- }
- my $token = &Apache::lonnet::tmpput(\%link_info,$desthost,'link');
- unless (($token eq 'con_lost') || ($token eq 'refused') ||
- ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {
- $url .= (($url=~/\?/)?'&':'?') . 'ttoken='.$token;
+ my %link_info = &Apache::lonnet::tmpget($env{'form.ltoken'});
+ &Apache::lonnet::tmpdel($env{'form.ltoken'});
+ my $token = &Apache::lonnet::tmpput(\%link_info,$desthost,'link');
+ unless (($token eq 'con_lost') || ($token eq 'refused') || ($token =~ /^error:/) ||
+ ($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {
+ unless (($path eq '/adm/roles') || ($path eq '/adm/login')) {
+ $url = $protocol.'://'.$hostname.'/adm/roles';
+ }
+ $querystring .= (($querystring =~/^\?/)?'&':'?') . 'ttoken='.$token;
+ }
}
+ $url .= $querystring;
}
my $start_page = &Apache::loncommon::start_page('Switching Server ...',undef,
{'redirect' => [0,$url],});
Index: loncom/auth/lonshibauth.pm
diff -u loncom/auth/lonshibauth.pm:1.14 loncom/auth/lonshibauth.pm:1.15
--- loncom/auth/lonshibauth.pm:1.14 Sun Dec 12 20:49:26 2021
+++ loncom/auth/lonshibauth.pm Sat Jun 18 02:10:18 2022
@@ -2,7 +2,7 @@
# Redirect Single Sign On authentication to designated URL:
# /adm/sso, by default.
#
-# $Id: lonshibauth.pm,v 1.14 2021/12/12 20:49:26 raeburn Exp $
+# $Id: lonshibauth.pm,v 1.15 2022/06/18 02:10:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -293,6 +293,10 @@
&Apache::lonacc::get_posted_cgi($r,['linkkey']);
}
}
+ unless (($r->is_initial_req()) || ($env{'form.ltoken'}) ||
+ ($env{'form.linkkey'})) {
+ return;
+ }
}
my $extras;
foreach my $name (@names) {
@@ -302,6 +306,9 @@
&Apache::lonnet::tmpdel($env{'form.ltoken'});
if ($info{'linkprot'}) {
$extras .= '&linkprot='.&escape($info{'linkprot'});
+ if ($info{'linkprotuser'} ne '') {
+ $extras .= '&linkprotuser='.&escape($info{'linkprotuser'});
+ }
last;
}
} else {
Index: loncom/auth/migrateuser.pm
diff -u loncom/auth/migrateuser.pm:1.60 loncom/auth/migrateuser.pm:1.61
--- loncom/auth/migrateuser.pm:1.60 Sat May 21 06:28:35 2022
+++ loncom/auth/migrateuser.pm Sat Jun 18 02:10:18 2022
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Starts a user off based of an existing token.
#
-# $Id: migrateuser.pm,v 1.60 2022/05/21 06:28:35 raeburn Exp $
+# $Id: migrateuser.pm,v 1.61 2022/06/18 02:10:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -285,7 +285,7 @@
'username' => $dataref->{'username'},
'sessionserver' => $lonhost,
);
- my @names = ('origurl','symb','role','linkprot','linkkey');
+ my @names = ('origurl','symb','role','linkprotuser','linkprot','linkkey');
foreach my $name (@names) {
if ($dataref->{$name} ne '') {
$info{$name} = $dataref->{$name};
@@ -308,7 +308,7 @@
}
sub logout {
- my ($r,$ip,$handle,$data,$lti_env) = @_;
+ my ($r,$ip,$handle,$data,$lti_env,$linkprot_info) = @_;
my $lonidsdir=$r->dir_config('lonIDsDir');
if (unlink("$lonidsdir/$handle.id")) {
if (($env{'user.linkedenv'} =~ /^[a-f0-9]+_linked$/) &&
@@ -335,15 +335,8 @@
-expires => '-10y',);
$r->headers_out->add('Set-cookie' => $c);
}
- my (%info,%user_info,%lti_info);
- if (ref($lti_env) eq 'HASH') {
- foreach my $key (sort(keys(%{$lti_env}))) {
- if ($key =~ /^request\.(.+)$/) {
- $lti_info{$1} = $lti_env->{$key};
- }
- }
- }
my $lonhost = $r->dir_config('lonHostID');
+ my ($url,$token,%info,%user_info);
if (ref($data) eq 'HASH') {
%user_info=('ip' => $ip,
'domain' => $data->{'domain'},
@@ -354,9 +347,33 @@
'symb' => $data->{'symb'},
'server' => $lonhost);
}
- %info = (%user_info,%lti_info);
- my $token = &Apache::lonnet::tmpput(\%info,$lonhost);
- my $url = '/adm/migrateuser?token='.$token;
+ if (ref($linkprot_info) eq 'HASH') {
+ if ($linkprot_info->{'linkprotuser'} ne '') {
+ $token = &Apache::lonnet::tmpput($linkprot_info,$lonhost);
+ $url = '/adm/login?ltoken='.$token;
+ } else {
+ foreach my $key (keys(%user_info)) {
+ if ($user_info{$key} eq '') {
+ delete($user_info{$key});
+ }
+ }
+ %info = (%user_info,%{$linkprot_info});
+ $token = &Apache::lonnet::tmpput(\%info,$lonhost);
+ $url = '/adm/migrateuser?token='.$token;
+ }
+ } else {
+ my %lti_info;
+ if (ref($lti_env) eq 'HASH') {
+ foreach my $key (sort(keys(%{$lti_env}))) {
+ if ($key =~ /^request\.(.+)$/) {
+ $lti_info{$1} = $lti_env->{$key};
+ }
+ }
+ }
+ %info = (%user_info,%lti_info);
+ $token = &Apache::lonnet::tmpput(\%info,$lonhost);
+ $url = '/adm/migrateuser?token='.$token;
+ }
$r->send_http_header;
$r->print(
&Apache::loncommon::start_page('Updating Session ...',undef,
@@ -738,10 +755,10 @@
my %linkprot_env;
foreach my $item ('linkprot','deeplink.login') {
if ($data{$item}) {
- $linkprot_env{'request.'.$item} = $data{$item};
+ $linkprot_env{$item} = $data{$item};
}
}
- &logout($r,$ip,$handle,\%data,\%linkprot_env);
+ &logout($r,$ip,$handle,\%data,undef,\%linkprot_env);
return OK;
}
&Apache::lonnet::appenv({'request.linkprot' => $data{'linkprot'}});
@@ -891,7 +908,7 @@
$info{'checklaunch'} = 1;
}
my $token = &Apache::lonnet::tmpput(\%info,$r->dir_config('lonHostID'),'link');
- unless (($token eq 'con_lost') || ($token eq 'refused') ||
+ unless (($token eq 'con_lost') || ($token eq 'refused') || ($token =~ /^error:/) ||
($token eq 'unknown_cmd') || ($token eq 'no_such_host')) {
$dest .= (($dest =~ /\?/) ? '&' : '?') . 'ttoken='.$token;
}
Index: loncom/auth/switchserver.pm
diff -u loncom/auth/switchserver.pm:1.59 loncom/auth/switchserver.pm:1.60
--- loncom/auth/switchserver.pm:1.59 Tue Oct 26 14:20:40 2021
+++ loncom/auth/switchserver.pm Sat Jun 18 02:10:18 2022
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Switch Servers Handler
#
-# $Id: switchserver.pm,v 1.59 2021/10/26 14:20:40 raeburn Exp $
+# $Id: switchserver.pm,v 1.60 2022/06/18 02:10:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -97,7 +97,7 @@
sub handler {
my ($r) = @_;
-
+
my $handle=&init_env($r);
if (!defined($handle)) { return FORBIDDEN; }
@@ -312,6 +312,9 @@
}
if ($env{'request.linkprot'}) {
$info{'linkprot'} = $env{'request.linkprot'};
+ if ($env{'request.linkprotuser'}) {
+ $info{'linkprotuser'} = $env{'request.linkprotuser'};
+ }
} elsif ($env{'request.linkkey'} ne '') {
$info{'linkkey'} = $env{'request.linkkey'};
}
Index: loncom/lti/ltiauth.pm
diff -u loncom/lti/ltiauth.pm:1.36 loncom/lti/ltiauth.pm:1.37
--- loncom/lti/ltiauth.pm:1.36 Wed Apr 6 21:44:49 2022
+++ loncom/lti/ltiauth.pm Sat Jun 18 02:10:19 2022
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Basic LTI Authentication Module
#
-# $Id: ltiauth.pm,v 1.36 2022/04/06 21:44:49 raeburn Exp $
+# $Id: ltiauth.pm,v 1.37 2022/06/18 02:10:19 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -31,7 +31,7 @@
use strict;
use LONCAPA qw(:DEFAULT :match);
use Encode;
-use Apache::Constants qw(:common :http);
+use Apache::Constants qw(:common :http :remotehost);
use Apache::lonlocal;
use Apache::lonnet;
use Apache::loncommon;
@@ -117,7 +117,7 @@
#
if ($requri =~ m{^/adm/launch(|/.*)$}) {
my $tail = $1;
- if ($tail =~ m{^/tiny/($match_domain)/(\w+)$}) {
+ if ($tail =~ m{^/tiny/$match_domain/\w+$}) {
my ($urlcdom,$urlcnum) = &course_from_tinyurl($tail);
if (($urlcdom ne '') && ($urlcnum ne '')) {
$cdom = $urlcdom;
@@ -143,7 +143,7 @@
# where url was /adm/launch/tiny/$cdom/$uniqueid
#
- my ($itemid,$ltitype,%crslti,%lti_in_use);
+ my ($itemid,$ltitype,%crslti,%lti_in_use,$ltiuser);
$itemid = &get_lti_itemid($requri,$hostname,$params,$cdom,$cnum,'linkprot');
if ($itemid) {
%crslti = &Apache::lonnet::get_course_lti($cnum,$cdom);
@@ -229,6 +229,7 @@
return OK;
}
}
+ $ltiuser = $uname.':'.$cdom;
}
}
if ($lti_in_use{'notstudent'} eq 'reject') {
@@ -241,13 +242,20 @@
foreach my $key (%{$params}) {
delete($env{'form.'.$key});
}
- my $ltoken = &Apache::lonnet::tmpput({'linkprot' => $itemid.$ltitype.':'.$tail},
- $lonhost,'link');
- if ($ltoken) {
+ my %info = (
+ 'linkprot' => $itemid.$ltitype.':'.$tail,
+ );
+ if ($ltiuser ne '') {
+ $info{'linkprotuser'} = $ltiuser;
+ }
+ my $ltoken = &Apache::lonnet::tmpput(\%info,$lonhost,'link');
+ if (($ltoken eq 'con_lost') || ($ltoken eq 'refused') || ($ltoken =~ /^error:/) ||
+ ($ltoken eq 'unknown_cmd') || ($ltoken eq 'no_such_host') ||
+ ($ltoken eq '')) {
+ &invalid_request($r,'Failed to store information from launch request');
+ } else {
$r->internal_redirect($tail.'?ltoken='.$ltoken);
$r->set_handlers('PerlHandler'=> undef);
- } else {
- &invalid_request($r,'Failed to store information from launch request');
}
} else {
&invalid_request($r,'Launch request could not be validated');
@@ -986,7 +994,7 @@
$r->dir_config('ltiIDsDir'),
$protocol,$r->hostname);
}
- my $ip = $r->get_remote_host();
+ my $ip = &Apache::lonnet::get_requestor_ip($r,REMOTE_NOLOOKUP);
my %info=('ip' => $ip,
'domain' => $udom,
'username' => $uname,
@@ -1075,7 +1083,7 @@
$r->set_handlers('PerlHandler'=> undef);
} else {
# need to login them in, so generate the data migrate expects to do login
- my $ip = $r->get_remote_host();
+ my $ip = &Apache::lonnet::get_requestor_ip($r,REMOTE_NOLOOKUP);
my %info=('ip' => $ip,
'domain' => $cdom,
'username' => $uname,
Index: loncom/lontrans.pm
diff -u loncom/lontrans.pm:1.38 loncom/lontrans.pm:1.39
--- loncom/lontrans.pm:1.38 Mon Dec 6 03:31:54 2021
+++ loncom/lontrans.pm Sat Jun 18 02:10:19 2022
@@ -1,7 +1,7 @@
# The LearningOnline Network
# URL translation for User Files
#
-# $Id: lontrans.pm,v 1.38 2021/12/06 03:31:54 raeburn Exp $
+# $Id: lontrans.pm,v 1.39 2022/06/18 02:10:19 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -276,8 +276,11 @@
my %link_info = &Apache::lonnet::tmpget($info{'ltoken'});
if ($link_info{'linkprot'}) {
$info{'linkprot'} = $link_info{'linkprot'};
+ if ($link_info{'linkprotuser'} ne '') {
+ $info{'linkprotuser'} = $link_info{'linkprotuser'};
+ }
}
- &Apache::lonnet::tmpdel($info{'ltoken'});;
+ &Apache::lonnet::tmpdel($info{'ltoken'});
delete($info{'ltoken'});
}
unless ($info{'role'}) {
Index: loncom/loncapa_apache.conf
diff -u loncom/loncapa_apache.conf:1.276 loncom/loncapa_apache.conf:1.277
--- loncom/loncapa_apache.conf:1.276 Sat Oct 2 13:54:29 2021
+++ loncom/loncapa_apache.conf Sat Jun 18 02:10:19 2022
@@ -2,7 +2,7 @@
## loncapa_apache.conf -- Apache HTTP LON-CAPA configuration file
##
-# $Id: loncapa_apache.conf,v 1.276 2021/10/02 13:54:29 raeburn Exp $
+# $Id: loncapa_apache.conf,v 1.277 2022/06/18 02:10:19 raeburn Exp $
#
# LON-CAPA Section (extensions to httpd.conf daemon configuration)
@@ -775,6 +775,11 @@
PerlHandler Apache::ltiauth
</LocationMatch>
+<Location /adm/relaunch>
+SetHandler perl-script
+PerlHandler Apache::lonrelaunch
+</Location>
+
<LocationMatch "^/+adm/lti($|/)">
SetHandler perl-script
PerlHandler Apache::ltiauth
Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.1029 doc/loncapafiles/loncapafiles.lpml:1.1030
--- doc/loncapafiles/loncapafiles.lpml:1.1029 Sat Jun 11 14:51:49 2022
+++ doc/loncapafiles/loncapafiles.lpml Sat Jun 18 02:10:20 2022
@@ -2,7 +2,7 @@
"http://lpml.sourceforge.net/DTD/lpml.dtd">
<!-- loncapafiles.lpml -->
-<!-- $Id: loncapafiles.lpml,v 1.1029 2022/06/11 14:51:49 raeburn Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.1030 2022/06/18 02:10:20 raeburn Exp $ -->
<!--
@@ -6961,6 +6961,16 @@
<status>works/unverified</status>
</file>
<file>
+ <source>loncom/auth/lonrelaunch.pm</source>
+ <target dist='default'>home/httpd/lib/perl/Apache/lonrelaunch.pm</target>
+ <categoryname>handler</categoryname>
+ <description>For a deep link protected by LTI where username is included
+ in launch payload, expire user's current session if username
+ from payload does not match username in LON-CAPA session.
+ </description>
+ <status>works/unverified</status>
+</file>
+<file>
<source>loncom/auth/lonshibauth.pm</source>
<target dist='default'>home/httpd/lib/perl/Apache/lonshibauth.pm</target>
<categoryname>handler</categoryname>
Index: loncom/auth/lonrelaunch.pm
+++ loncom/auth/lonrelaunch.pm
# The LearningOnline Network
# Re-launch guidance for deep linked access with username mismatch
#
# $Id: lonrelaunch.pm,v 1.1 2022/06/18 02:10:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
package Apache::lonrelaunch;
use strict;
use lib '/home/httpd/lib/perl/';
use Apache::Constants qw(:common :http REDIRECT);
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonlocal;
use LONCAPA qw(:DEFAULT :match);
use CGI::Cookie();
sub handler {
my $r = shift;
my %data;
if ($r->args) {
&Apache::loncommon::get_unprocessed_cgi($r->args,['rtoken']);
if (exists($env{'form.rtoken'})) {
%data = &Apache::lonnet::tmpget($env{'form.rtoken'});
my $delete = &Apache::lonnet::tmpdel($env{'form.rtoken'});
}
}
my $handle = &Apache::lonnet::check_for_valid_session($r);
if ($handle ne '') {
my $lonidsdir=$r->dir_config('lonIDsDir');
&Apache::lonnet::transfer_profile_to_env($lonidsdir,$handle);
if (unlink("$lonidsdir/$handle.id")) {
if (($env{'user.linkedenv'} =~ /^[a-f0-9]+_linked$/) &&
(-l "$lonidsdir/$env{'user.linkedenv'}.id") &&
(readlink("$lonidsdir/$env{'user.linkedenv'}.id") eq "$lonidsdir/$handle.id")) {
unlink("$lonidsdir/$env{'user.linkedenv'}.id");
}
}
my %temp=('logout' => time);
my $ip = &Apache::lonnet::get_requestor_ip();
&Apache::lonnet::put('email_status',\%temp);
&Apache::lonnet::log($env{'user.domain'},
$env{'user.name'},
$env{'user.home'},
"Logout $ip");
#expire the cookies
my %cookies=CGI::Cookie->parse($r->header_in('Cookie'));
foreach my $name (keys(%cookies)) {
next unless ($name =~ /^lon(|S|Link|Pub)ID$/);
my $c = new CGI::Cookie(-name => $name,
-value => '',
-expires => '-10y',);
$r->headers_out->add('Set-cookie' => $c);
}
}
if (!$Apache::lonlocal::lh) {
&Apache::lonlocal::get_language_handle($r);
}
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK if $r->header_only;
if ((keys(%data)) && ($data{'origurl'} =~ m{^/tiny/$match_domain/\w+$})) {
my $url = $data{'origurl'};
if (($data{'linkprot'} =~ m{^\w+(c|d):\Q$url\E$}) &&
($data{'linkprotuser'} =~ m{^($match_username):($match_domain)$})) {
my $brcrum = [{'href' => '','text' => 'Update session'},];
$url .= '?ltoken='.$env{'form.rtoken'};
$r->print(&Apache::loncommon::start_page('Updating session',undef,
{'only_body' => 1,
'redirect' => [1,$url],
'bread_crumbs' => $brcrum,}).
'<p>'.&mt('Updating old session information').'</p>'.
&Apache::loncommon::end_page());
return OK;
}
}
$r->print(&Apache::loncommon::start_page('Username mismatch',undef,{'only_body' => 1}));
$r->print(&mt('Although your credentials were authenticated, the username you entered did not match what was expected [_1] from the link you followed',"($data{'linkprotuser'})"));
$r->print(&Apache::loncommon::end_page());
return OK;
}
1;
More information about the LON-CAPA-cvs
mailing list