Commit 47f9865e authored by Xavier Guimard's avatar Xavier Guimard

SAML in progress (#595)

parent 0c871ecd
......@@ -392,6 +392,9 @@ sub extractFormInfo {
elsif ( $url =~ $self->sloRe ) {
$self->lmLog( "URL $url detected as an SLO URL", 'debug' );
# TODO: call authLogout instead of duplicating SLO
$req->steps( [ @{ $self->p->beforeLogout }, 'deleteSession' ] );
# Check SAML Message
my ( $request, $response, $method, $relaystate, $artifact ) =
$self->checkMessage( $req, $url, $request_method, $content_type,
......@@ -482,11 +485,13 @@ sub extractFormInfo {
and $self->conf->{portal} !~ /$req->{urldc}\/?/ )
{
$req->steps( [] );
$req->user('TODO');
return PE_OK;
}
# Else, inform user that logout is OK
return PE_LOGOUT_OK;
$req->user('TODO');
return PE_OK;
}
elsif ($request) {
......@@ -602,6 +607,9 @@ sub extractFormInfo {
my $ssoSession =
$self->p->getApacheSession( $real_session, 1 );
# Import SSO session in $req
$self->importRealSession( $req, $ssoSession );
# Get Lasso::Session dump
# This value is erased if a next session match the SLO request
if ( $ssoSession
......@@ -615,16 +623,7 @@ sub extractFormInfo {
$ssoSession->data->{_lassoSessionDump};
}
# Delete real session
my $del_real_result =
$self->p->_deleteSession( $req, $ssoSession );
$self->lmLog(
"Delete real session $real_session result: $del_real_result",
'debug'
);
$logout_error = 1 unless $del_real_result;
# Real session will be deleted after (see $req->steps... before)
# Delete SAML session
my $del_saml_result = $sessionInfo->remove();
......@@ -749,8 +748,20 @@ sub extractFormInfo {
[$slo_body]
]
);
$req->steps(
[
@{ $self->p->beforeLogout },
sub {
my ($req) = @_;
my $res = $self->p->deleteSession($req);
return (
$res eq PE_LOGOUT_OK ? PE_SENDRESPONSE : $res );
}
]
);
return PE_SENDRESPONSE;
$req->user('SOAP client');
return PE_OK;
}
}
......@@ -1333,7 +1344,7 @@ sub authLogout {
if ( $logout->msg_relayState );
# Post done in Portal/Simple.pm
$req->steps( ['autoPost'] );
$req->steps( [ 'deleteSession', 'autoPost' ] );
return PE_OK;
}
......@@ -1481,7 +1492,7 @@ sub getIDP {
# Alert when selected IDP is unknown
if ( $idp and !exists $self->idpList->{$idp} ) {
$self->userError("Required IDP $idp does not exists");
$self->p->userError("Required IDP $idp does not exists");
$idp = undef;
}
......
......@@ -92,6 +92,10 @@ qr/^($saml_slo_get_url|$saml_slo_get_url_ret|$saml_slo_post_url|$saml_slo_post_u
2, 'soapSloServer', ['POST'] );
# TODO: @coudot, why this URL isn't managed with a conf param ?
$self->addUnauthRoute(
$self->path => { relaySingleLogoutSOAP => 'sloRelaySoap' },
[ 'GET', 'POST' ]
);
$self->addAuthRoute(
$self->path => { relaySingleLogoutSOAP => 'sloRelaySoap' },
[ 'GET', 'POST' ]
......@@ -1439,7 +1443,7 @@ sub logout {
# Redirect on logout page when all is done.
if ( $self->sendLogoutRequestToProviders( $req, $logout ) ) {
$self->{urldc} = $req->scriptname . "?logout=1";
return PE_INFO;
return PE_OK;
}
return PE_OK;
......
......@@ -2363,7 +2363,7 @@ sub sendLogoutResponseToServiceProvider {
$req->{postFields}->{'RelayState'} = $relaystate
if ($relaystate);
$req->steps( ['autoPost'] );
$req->steps( [ 'deleteSession', 'autoPost' ] );
return PE_OK;
}
$self->lmLog( "Lasso method '$method' should not be handle here...",
......@@ -2444,6 +2444,7 @@ sub sendLogoutRequestToProvider {
);
return ( 0, $method, undef );
}
$self->lmLog( 'Relay state set', 'debug' );
}
# Build the request
......@@ -2465,6 +2466,7 @@ sub sendLogoutRequestToProvider {
return ( 0, $method, undef );
}
$self->lmLog( "Request built for $providerID", 'debug' );
}
# Keep message ID in memory to prevent replay
......@@ -3024,6 +3026,13 @@ sub getQueryString {
return $query_string;
}
sub importRealSession {
my ( $self, $req, $ssoSession ) = @_;
$req->sessionInfo( $ssoSession->data );
$req->id( $ssoSession->id );
$req->user( $ssoSession->data->{ $self->conf->{whatToTrace} } );
}
1;
__END__
......
......@@ -127,13 +127,18 @@ sub authLogout {
sub deleteSession {
my ( $self, $req ) = @_;
my $apacheSession = $self->getApacheSession( $req->id );
my $id = $req->id;
unless ($apacheSession) {
$self->lmLog( "Session $id already deleted", 'debug' );
return PE_OK;
}
unless ( $self->_deleteSession( $req, $apacheSession ) ) {
$self->lmLog( "Unable to delete session " . $req->id, 'error' );
$self->lmLog( $apacheSession->error, 'error' );
$self->lmLog( "Unable to delete session $id", 'error' );
$self->lmLog( $apacheSession->error, 'error' );
return PE_ERROR;
}
else {
$self->lmLog( "Session $req->{id} deleted from global storage",
$self->lmLog( "Session $id deleted from global storage",
'debug' );
}
......@@ -169,7 +174,8 @@ sub deleteSession {
# Redirect on logout page if no other target defined
if ( !$req->urldc and !$req->postUrl ) {
$self->lmLog('No other target defined, redirect on logout','debug');
$self->lmLog( 'No other target defined, redirect on logout',
'debug' );
$req->urldc( $req->scriptname . "?logout=1" );
}
}
......
......@@ -260,7 +260,7 @@ sub getApacheSession {
);
if ( $as->error ) {
$self->lmLog( $as->error, 'error' );
$self->lmLog( $as->error, 'info' );
return;
}
......@@ -444,7 +444,7 @@ sub _deleteSession {
) unless ($preserveCookie);
}
HANDLER->unlog($session->id);
HANDLER->unlog( $session->id );
$session->remove;
# Create an obsolete cookie to remove it
......
......@@ -7,7 +7,7 @@ BEGIN {
require 't/test-lib.pm';
}
my $maintests = 12;
my $maintests = 14;
my $debug = 'error';
my ( $issuer, $sp, $res );
my %handlerOR = ( issuer => [], sp => [] );
......@@ -72,7 +72,7 @@ SKIP: {
length => length($s),
cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata',
),
'Post SAML response to SP'
'Post SAML logout response to SP'
);
# Verify authentication on SP
......@@ -114,6 +114,28 @@ m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
ok( getHeader( $res, 'Content-Type' ) eq 'image/png', 'Get an image' )
or explain( [ $res->[0], $res->[1] ], 'Content-Type => image/png' );
# Test if logout is done
switch ('issuer');
ok(
$res = $sp->_get(
'/', cookie => "lemonldap=$idpId",
),
'Test if user is reject on IdP'
);
expectReject($res);
switch ('sp');
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
),
'Test if user is reject on SP'
);
expectRedirection( $res,
qr#^http://auth.idp.com/saml/singleSignOn\?(SAMLRequest=.*)# );
}
count($maintests);
......
......@@ -7,7 +7,7 @@ BEGIN {
require 't/test-lib.pm';
}
my $maintests = 12;
my $maintests = 14;
my $debug = 'error';
my ( $issuer, $sp, $res );
my %handlerOR = ( issuer => [], sp => [] );
......@@ -137,6 +137,29 @@ SKIP: {
'Query SP for logout'
);
# Test if logout is done
switch ('issuer');
ok(
$res = $sp->_get(
'/', cookie => "lemonldap=$idpId",
),
'Test if user is reject on IdP'
);
expectReject($res);
switch ('sp');
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
),
'Test if user is reject on SP'
);
expectRedirection( $res,
qr#^http://auth.idp.com/saml/singleSignOn\?(SAMLRequest=.*)# );
#print STDERR Dumper($res);
}
......
......@@ -7,7 +7,7 @@ BEGIN {
require 't/test-lib.pm';
}
my $maintests = 12;
my $maintests = 15;
my $debug = 'error';
my ( $issuer, $sp, $res );
my %handlerOR = ( issuer => [], sp => [] );
......@@ -114,6 +114,36 @@ m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
ok( getHeader( $res, 'Content-Type' ) eq 'image/png', 'Get an image' )
or explain( [ $res->[0], $res->[1] ], 'Content-Type => image/png' );
# Test if logout is done
switch ('issuer');
ok(
$res = $sp->_get(
'/', cookie => "lemonldap=$idpId",
),
'Test if user is reject on IdP'
);
expectReject($res);
switch ('sp');
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
),
'Test if user is reject on SP'
);
expectOK($res);
ok(
$res->[2]->[0] =~
/<input type="hidden".+?name="SAMLRequest".+?value="(.+?)"/s,
'Found SAML request'
)
or explain(
$res->[2],
' <input type="hidden" name="SAMLRequest" id="SAMLRequest" value="...'
);
}
count($maintests);
......@@ -125,7 +155,7 @@ no warnings 'redefine';
sub LWP::UserAgent::request {
my ( $self, $req ) = @_;
ok( $req->uri =~ m#http://auth.sp.com(.*)#, 'Request from SP to IdP' );
ok( $req->uri =~ m#http://auth.sp.com(.*)#, 'Request from IdP to SP' );
my $url = $1;
my $res;
my $s = $req->content;
......
......@@ -7,7 +7,7 @@ BEGIN {
require 't/test-lib.pm';
}
my $maintests = 25;
my $maintests = 28;
my $debug = 'error';
my ( $issuer, $sp, $res );
my %handlerOR = ( issuer => [], sp => [] );
......@@ -228,6 +228,37 @@ SKIP: {
);
expectRedirection( $res, 'http://auth.sp.com' );
# Test if logout is done
switch ('issuer');
ok(
$res = $sp->_get(
'/', cookie => "lemonldap=$idpId",
),
'Test if user is reject on IdP'
);
expectReject($res);
switch ('sp');
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
),
'Test if user is reject on SP'
);
expectOK($res);
ok(
$res->[2]->[0] =~
/<input type="hidden".+?name="SAMLRequest".+?value="(.+?)"/s,
'Found SAML request'
);
#or explain(
# $res->[2],
# ' <input type="hidden" name="SAMLRequest" id="SAMLRequest" value="...'
#);
#print STDERR Dumper($res);
}
......
......@@ -7,7 +7,7 @@ BEGIN {
require 't/test-lib.pm';
}
my $maintests = 12;
my $maintests = 14;
my $debug = 'error';
my ( $issuer, $sp, $res );
my %handlerOR = ( issuer => [], sp => [] );
......@@ -114,6 +114,28 @@ m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
ok( getHeader( $res, 'Content-Type' ) eq 'image/png', 'Get an image' )
or explain( [ $res->[0], $res->[1] ], 'Content-Type => image/png' );
# Test if logout is done
switch ('issuer');
ok(
$res = $sp->_get(
'/', cookie => "lemonldap=$idpId",
),
'Test if user is reject on IdP'
);
expectReject($res);
switch ('sp');
ok(
$res = $sp->_get(
'/',
accept => 'text/html',
cookie =>
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
),
'Test if user is reject on SP'
);
expectRedirection( $res,
qr#^http://auth.idp.com/saml/singleSignOn\?(SAMLRequest=.*)# );
}
count($maintests);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment