SAML SLO in progress (#595)
This commit is contained in:
parent
76dffd04b2
commit
a959d77e1c
|
@ -1285,8 +1285,8 @@ sub authLogout {
|
||||||
|
|
||||||
# Build Logout Request
|
# Build Logout Request
|
||||||
my $logout =
|
my $logout =
|
||||||
$self->createLogoutRequest( $self->lassoServer, $session_dump, $method,
|
$self->createLogoutRequest( $req, $self->lassoServer, $session_dump,
|
||||||
$signSLOMessage );
|
$method, $signSLOMessage );
|
||||||
unless ($logout) {
|
unless ($logout) {
|
||||||
$self->lmLog( "Could not create logout request", 'error' );
|
$self->lmLog( "Could not create logout request", 'error' );
|
||||||
return PE_SAML_SLO_ERROR;
|
return PE_SAML_SLO_ERROR;
|
||||||
|
@ -1322,13 +1322,14 @@ sub authLogout {
|
||||||
my $slo_body = $logout->msg_body;
|
my $slo_body = $logout->msg_body;
|
||||||
|
|
||||||
$req->postUrl($slo_url);
|
$req->postUrl($slo_url);
|
||||||
$self->postFields( { 'SAMLRequest' => $slo_body } );
|
$req->postFields( { 'SAMLRequest' => $slo_body } );
|
||||||
|
|
||||||
# RelayState
|
# RelayState
|
||||||
$self->postFields->{'RelayState'} = $logout->msg_relayState
|
$self->postFields->{'RelayState'} = $logout->msg_relayState
|
||||||
if ( $logout->msg_relayState );
|
if ( $logout->msg_relayState );
|
||||||
|
|
||||||
# Post done in Portal/Simple.pm
|
# Post done in Portal/Simple.pm
|
||||||
|
$req->steps( ['autoPost'] );
|
||||||
return PE_OK;
|
return PE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,11 @@ use POSIX qw(strftime); # Convert SAML2 date into timestamp
|
||||||
use Time::Local; # Convert SAML2 date into timestamp
|
use Time::Local; # Convert SAML2 date into timestamp
|
||||||
use Encode; # Encode attribute values
|
use Encode; # Encode attribute values
|
||||||
use URI; # Get metadata URL path
|
use URI; # Get metadata URL path
|
||||||
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
|
PE_OK
|
||||||
|
PE_REDIRECT
|
||||||
|
PE_SAML_SLO_ERROR
|
||||||
|
);
|
||||||
|
|
||||||
our $VERSION = '2.0.0';
|
our $VERSION = '2.0.0';
|
||||||
|
|
||||||
|
@ -2289,7 +2294,7 @@ sub sendLogoutResponseToServiceProvider {
|
||||||
# Logout response
|
# Logout response
|
||||||
unless ( $self->buildLogoutResponseMsg($logout) ) {
|
unless ( $self->buildLogoutResponseMsg($logout) ) {
|
||||||
$self->lmLog( "Unable to build SLO response", 'error' );
|
$self->lmLog( "Unable to build SLO response", 'error' );
|
||||||
return 0;
|
return PE_SAML_SLO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Send response depending on request method
|
# Send response depending on request method
|
||||||
|
@ -2303,7 +2308,7 @@ sub sendLogoutResponseToServiceProvider {
|
||||||
$self->lmLog( "Redirect user to $slo_url", 'debug' );
|
$self->lmLog( "Redirect user to $slo_url", 'debug' );
|
||||||
|
|
||||||
die 'TODO: autoRedirect must not be called now';
|
die 'TODO: autoRedirect must not be called now';
|
||||||
return $self->autoRedirect;
|
return PE_REDIRECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTTP-POST
|
# HTTP-POST
|
||||||
|
@ -2323,7 +2328,8 @@ sub sendLogoutResponseToServiceProvider {
|
||||||
if ($relaystate);
|
if ($relaystate);
|
||||||
|
|
||||||
die 'autoPost must not be called here';
|
die 'autoPost must not be called here';
|
||||||
return $self->autoPost;
|
$req->steps(['autoPost']);
|
||||||
|
return PE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTTP-SOAP
|
# HTTP-SOAP
|
||||||
|
@ -2340,7 +2346,7 @@ sub sendLogoutResponseToServiceProvider {
|
||||||
# If we are here, there was a problem with SOAP response
|
# If we are here, there was a problem with SOAP response
|
||||||
$self->lmLog( "Logout response was not sent trough SOAP", 'error' );
|
$self->lmLog( "Logout response was not sent trough SOAP", 'error' );
|
||||||
|
|
||||||
return 0;
|
return PE_SAML_SLO_ERROR;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2945,8 +2951,7 @@ sub sendSLOErrorResponse {
|
||||||
|
|
||||||
unless ( $self->setSessionFromDump( $logout, $session ) ) {
|
unless ( $self->setSessionFromDump( $logout, $session ) ) {
|
||||||
$self->lmLog( "Could not set empty session in logout object", 'error' );
|
$self->lmLog( "Could not set empty session in logout object", 'error' );
|
||||||
die 'Replace this';
|
return PE_SAML_SLO_ERROR;
|
||||||
$self->quit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Send unvalidated SLO response
|
# Send unvalidated SLO response
|
||||||
|
|
|
@ -36,7 +36,8 @@ sub init {
|
||||||
$path =~ s/^.*?(\w+).*?$/$1/;
|
$path =~ s/^.*?(\w+).*?$/$1/;
|
||||||
$self->addUnauthRoute( $path => '_redirect', ['GET'] );
|
$self->addUnauthRoute( $path => '_redirect', ['GET'] );
|
||||||
$self->addUnauthRoute( $path => '_pRedirect', ['POST'] );
|
$self->addUnauthRoute( $path => '_pRedirect', ['POST'] );
|
||||||
$self->addAuthRoute( $path => "_forAuthUser", [ 'GET', 'POST' ] );
|
$self->addAuthRoute( $path => "_forAuthUser", ['GET'] );
|
||||||
|
$self->addAuthRoute( $path => "_pForAuthUser", ['POST'] );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->lmLog( "No path declared for issuer $type. Skipping", 'debug' );
|
$self->lmLog( "No path declared for issuer $type. Skipping", 'debug' );
|
||||||
|
@ -53,8 +54,8 @@ sub _redirect {
|
||||||
foreach my $k ( keys %$prms ) {
|
foreach my $k ( keys %$prms ) {
|
||||||
$self->p->setHiddenFormValue( $req, $k, $prms->{$k}, '', 0 );
|
$self->p->setHiddenFormValue( $req, $k, $prms->{$k}, '', 0 );
|
||||||
}
|
}
|
||||||
$self->p->setHiddenFormValue( $req, 'issuerMethod', $req->method, '', 0);
|
$self->p->setHiddenFormValue( $req, 'issuerMethod', $req->method, '', 0 );
|
||||||
$self->p->setHiddenFormValue( $req, 'issuerQuery', $req->query, '', 0);
|
$self->p->setHiddenFormValue( $req, 'issuerQuery', $req->query, '', 0 );
|
||||||
$req->{urldc} =
|
$req->{urldc} =
|
||||||
$self->conf->{portal}
|
$self->conf->{portal}
|
||||||
. $req->path
|
. $req->path
|
||||||
|
@ -79,6 +80,7 @@ sub _redirect {
|
||||||
|
|
||||||
sub _pRedirect {
|
sub _pRedirect {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
|
$self->lmLog( 'Parsing posted datas', 'debug' );
|
||||||
$req->parseBody;
|
$req->parseBody;
|
||||||
return $self->_redirect($req);
|
return $self->_redirect($req);
|
||||||
}
|
}
|
||||||
|
@ -99,4 +101,11 @@ sub _forAuthUser {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub _pForAuthUser {
|
||||||
|
my ( $self, $req ) = @_;
|
||||||
|
$self->lmLog( 'Parsing posted datas', 'debug' );
|
||||||
|
$req->parseBody;
|
||||||
|
return $self->_forAuthUser($req);
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -7,8 +7,8 @@ BEGIN {
|
||||||
require 't/test-lib.pm';
|
require 't/test-lib.pm';
|
||||||
}
|
}
|
||||||
|
|
||||||
my $maintests = 26;
|
my $maintests = 33;
|
||||||
my $debug = 'error';
|
my $debug = 'debug';
|
||||||
my $res;
|
my $res;
|
||||||
my %handlerOR = ( issuer => [], sp => [] );
|
my %handlerOR = ( issuer => [], sp => [] );
|
||||||
|
|
||||||
|
@ -178,6 +178,50 @@ SKIP: {
|
||||||
'User is identified as dwho@badwolf.org@idp'
|
'User is identified as dwho@badwolf.org@idp'
|
||||||
) or explain( $res->[1], 'Lm-Remote-User: dwho@badwolf.org@idp' );
|
) or explain( $res->[1], 'Lm-Remote-User: dwho@badwolf.org@idp' );
|
||||||
|
|
||||||
|
# Logout initiated by SP
|
||||||
|
ok(
|
||||||
|
$res = $sp->_get(
|
||||||
|
'/',
|
||||||
|
query => 'logout',
|
||||||
|
cookie => "lemonldap=$spId",
|
||||||
|
accept => 'text/html'
|
||||||
|
),
|
||||||
|
'Query SP for logout'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 200, 'Return code is 200' );
|
||||||
|
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="...'
|
||||||
|
);
|
||||||
|
$samlReq = $1;
|
||||||
|
ok( decode_base64($samlReq) =~ /^</s, 'SAML request seems valid' )
|
||||||
|
or explain( decode_base64($samlReq), '<saml ...' );
|
||||||
|
ok(
|
||||||
|
$res->[2]->[0] =~ m#<form id="form" action="http://auth.idp.com(.*?)"#s,
|
||||||
|
'Found IdP URL'
|
||||||
|
);
|
||||||
|
$url = $1;
|
||||||
|
|
||||||
|
# Push SAML logout request to IdP
|
||||||
|
switch ('issuer');
|
||||||
|
$s = "SAMLRequest=$samlReq";
|
||||||
|
ok(
|
||||||
|
$res = $issuer->_post(
|
||||||
|
$url,
|
||||||
|
IO::String->new($s),
|
||||||
|
accept => 'text/html',
|
||||||
|
cookie => "lemonldap=$idpId",
|
||||||
|
length => length($s)
|
||||||
|
),
|
||||||
|
'Post SAML request to IdP'
|
||||||
|
);
|
||||||
|
ok( $res->[0] == 200, 'Return code is 200' );
|
||||||
|
|
||||||
#print STDERR Dumper($res);
|
#print STDERR Dumper($res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,6 +559,7 @@ sub sp {
|
||||||
idp => {
|
idp => {
|
||||||
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
||||||
samlIDPMetaDataOptionsSSOBinding => 'POST',
|
samlIDPMetaDataOptionsSSOBinding => 'POST',
|
||||||
|
samlIDPMetaDataOptionsSLOBinding => 'POST',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
samlIDPMetaDataXML => {
|
samlIDPMetaDataXML => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user