Commit aba27302 authored by Yadd's avatar Yadd

Split SLO from run [SAML] (#595)

parent a2be61bb
......@@ -26,10 +26,14 @@ our $VERSION = '2.0.0';
extends 'Lemonldap::NG::Portal::Auth::Base', 'Lemonldap::NG::Portal::Lib::SAML';
# INTERFACE
has sloAssConsumerRe => ( is => 'rw' );
has sloRe => ( is => 'rw' );
has artRe => ( is => 'rw' );
sub forAuthUser { 'handleAuthRequests' }
# INITIALIZATION
sub init {
......@@ -707,8 +711,7 @@ sub extractFormInfo {
$req->urldc($slo_url);
$req->steps( [] );
return PE_REDIRECT;
return PE_OK;
}
# HTTP-POST
......@@ -719,15 +722,14 @@ sub extractFormInfo {
my $slo_body = $logout->msg_body;
$req->postUrl($slo_url);
$req->postFields = { 'SAMLResponse' => $slo_body };
$req->postFields( { 'SAMLResponse' => $slo_body } );
# RelayState
$req->postFields->{'RelayState'} = $relaystate
if ($relaystate);
# TODO: verify this
$req->steps( ['autoPost'] );
$req->continue(1);
push @{ $req->steps }, 'autoPost';
return PE_OK;
}
......@@ -1389,6 +1391,14 @@ sub authLogout {
}
}
sub handleAuthRequests {
my ( $self, $req ) = @_;
if ( $req->uri =~ $self->sloRe ) {
return $self->extractFormInfo($req);
}
PE_OK;
}
# TODO: authForce
sub getDisplayType {
......
......@@ -401,6 +401,7 @@ sub checkMessage {
# 2.2.1. POST
if ( $content_type !~ /xml/ ) {
$req->parseBody unless(%{$req->params});
$method = Lasso::Constants::HTTP_METHOD_POST;
$self->lmLog( "SAML method: HTTP-POST", 'debug' );
......@@ -2330,8 +2331,7 @@ sub sendLogoutResponseToServiceProvider {
# Logout response
unless ( $self->buildLogoutResponseMsg($logout) ) {
$self->lmLog( "Unable to build SLO response", 'error' );
return PE_SAML_SLO_ERROR;
return $self->p->sendError( $req, "Unable to build SLO response", 500 );
}
# Send response depending on request method
......@@ -2340,11 +2340,7 @@ sub sendLogoutResponseToServiceProvider {
# Redirect user to response URL
my $slo_url = $logout->msg_url;
$req->urldc($slo_url);
$self->lmLog( "Redirect user to $slo_url", 'debug' );
return PE_REDIRECT;
return [ 302, [ Location => $slo_url ], [] ];
}
# HTTP-POST
......@@ -2363,13 +2359,10 @@ sub sendLogoutResponseToServiceProvider {
$req->{postFields}->{'RelayState'} = $relaystate
if ($relaystate);
$req->steps( [ 'deleteSession', 'autoPost' ] );
return PE_OK;
return $self->p->do( $req, ['autoPost'] );
}
$self->lmLog( "Lasso method '$method' should not be handle here...",
'error' );
return PE_SAML_SLO_ERROR;
return $self->p->sendError( $req,
"Lasso method '$method' should not be handle here...", 400 );
}
## @pmethod int sendLogoutRequestToProvider(Lasso::Logout $logout, string $providerID, int $method, boolean $relay, string $relayState)
......@@ -2969,15 +2962,15 @@ sub sendSLOErrorResponse {
'<Session xmlns="http://www.entrouvert.org/namespaces/lasso/0.0"/>';
unless ( $self->setSessionFromDump( $logout, $session ) ) {
$self->lmLog( "Could not set empty session in logout object", 'error' );
return PE_SAML_SLO_ERROR;
return $self->p->sendError( $req,
"Could not set empty session in logout object", 500 );
}
# Send unvalidated SLO response
return $self->sendLogoutResponseToServiceProvider( $req, $logout, $method );
}
## @method void sendSLOErrorResponse(Lasso::Logout logout, string method)
## @method void sendSLOSoapErrorResponse(Lasso::Logout logout, string method)
# Send an SLO error response
# @param logout Lasso::Logout object
# @param method HTTP method
......@@ -2990,8 +2983,8 @@ sub sendSLOSoapErrorResponse {
'<Session xmlns="http://www.entrouvert.org/namespaces/lasso/0.0"/>';
unless ( $self->setSessionFromDump( $logout, $session ) ) {
return $self->p->sendError(
"Could not set empty session in logout object");
return $self->p->sendError( $req,
"Could not set empty session in logout object" );
}
my $slo_body = $logout->msg_body;
$self->lmLog( "SOAP response $slo_body", 'debug' );
......
......@@ -53,6 +53,7 @@ sub init {
sub _redirect {
my ( $self, $req, @path ) = @_;
$self->lmLog('Processing _redirect','debug');
my $prms = $req->params;
foreach my $k ( keys %$prms ) {
$self->p->setHiddenFormValue( $req, $k, $prms->{$k}, '', 0 );
......@@ -83,7 +84,7 @@ sub _redirect {
sub _pRedirect {
my ( $self, $req, @path ) = @_;
$self->lmLog( 'Parsing posted datas', 'debug' );
$self->lmLog( '_pRedirect: parsing posted datas', 'debug' );
$req->parseBody;
return $self->_redirect( $req, @path );
}
......@@ -91,6 +92,7 @@ sub _pRedirect {
# Case 3: authentified user, launch
sub _forAuthUser {
my ( $self, $req, @path ) = @_;
$self->lmLog('Processing _forAuthUser','debug');
return $self->p->do(
$req,
[
......
......@@ -7,7 +7,7 @@ BEGIN {
require 't/test-lib.pm';
}
my $maintests = 15;
my $maintests = 20;
my $debug = 'error';
my ( $issuer, $sp, $res );
my %handlerOR = ( issuer => [], sp => [] );
......@@ -98,9 +98,9 @@ SKIP: {
ok(
$res->[2]->[0] =~
m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
'Get image request'
);
m#iframe src="http://auth.idp.com(/saml/relaySingleLogoutPOST)\?(relay=.*?)"#s,
'Get iframe request'
) or explain($res,'');
ok(
$res = $issuer->_get(
......@@ -109,10 +109,58 @@ m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
cookie => "lemonldap=$idpId",
accept => 'text/html'
),
'Get image'
'Get iframe'
);
expectOK($res);
ok(
$res->[2]->[0] =~
m#<form.+?action="http://auth.sp.com(/saml/proxySingleLogout)".+?method="post"#,
'Form method is POST'
);
$url = $1;
ok(
$res->[2]->[0] =~
/<input type="hidden".+?name="SAMLRequest".+?value="(.+?)"/s,
'Found SAML response'
);
$s = "SAMLRequest=$1";
# Post SAML logout request to SP
switch ('sp');
ok(
$res = $sp->_post(
$url, IO::String->new($s),
accept => 'text/html',
length => length($s),
cookie => "lemonldap=$spId",
),
'Post SAML logout request to SP'
);
expectOK($res);
ok(
$res->[2]->[0] =~
m#<form.+?action="http://auth.idp.com(/saml/singleLogoutReturn)".+?method="post"#,
'Form method is POST'
);
$url = $1;
ok(
$res->[2]->[0] =~
/<input type="hidden".+?name="SAMLResponse".+?value="(.+?)"/s,
'Found SAML response'
);
$s = "SAMLResponse=$1";
# Post SAML logout response to IdP
switch('issuer');
ok(
$res = $sp->_post(
$url, IO::String->new($s),
accept => 'text/html',
length => length($s),
cookie => "lemonldap=$spId",
),
'Post SAML logout response to IdP'
);
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');
......@@ -144,6 +192,7 @@ m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
$res->[2],
' <input type="hidden" name="SAMLRequest" id="SAMLRequest" value="...'
);
#print STDERR Dumper($res);
}
count($maintests);
......@@ -341,11 +390,6 @@ entityID="http://auth.sp.com/saml/metadata">
<ArtifactResolutionService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.sp.com/saml/artifact" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.sp.com/saml/singleLogoutSOAP" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://auth.sp.com/saml/singleLogout"
ResponseLocation="http://auth.sp.com/saml/singleLogoutReturn" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.sp.com/saml/singleLogout"
ResponseLocation="http://auth.sp.com/saml/singleLogoutReturn" />
......@@ -361,14 +405,8 @@ entityID="http://auth.sp.com/saml/metadata">
urn:oasis:names:tc:SAML:2.0:nameid-format:entity</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://auth.sp.com/saml/singleSignOn" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.sp.com/saml/singleSignOn" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://auth.sp.com/saml/singleSignOnArtifact" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.sp.com/saml/singleSignOnSOAP" />
</IDPSSODescriptor>
<SPSSODescriptor AuthnRequestsSigned="true"
WantAssertionsSigned="true"
......@@ -407,11 +445,6 @@ entityID="http://auth.sp.com/saml/metadata">
<ArtifactResolutionService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.sp.com/saml/artifact" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.sp.com/saml/proxySingleLogoutSOAP" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://auth.sp.com/saml/proxySingleLogout"
ResponseLocation="http://auth.sp.com/saml/proxySingleLogoutReturn" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.sp.com/saml/proxySingleLogout"
ResponseLocation="http://auth.sp.com/saml/proxySingleLogoutReturn" />
......@@ -430,9 +463,6 @@ entityID="http://auth.sp.com/saml/metadata">
<AssertionConsumerService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.sp.com/saml/proxySingleSignOnPost" />
<AssertionConsumerService isDefault="false" index="1"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://auth.sp.com/saml/proxySingleSignOnArtifact" />
</SPSSODescriptor>
<AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
......@@ -570,11 +600,6 @@ entityID="http://auth.idp.com/saml/metadata">
<ArtifactResolutionService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.idp.com/saml/artifact" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.idp.com/saml/singleLogoutSOAP" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://auth.idp.com/saml/singleLogout"
ResponseLocation="http://auth.idp.com/saml/singleLogoutReturn" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.idp.com/saml/singleLogout"
ResponseLocation="http://auth.idp.com/saml/singleLogoutReturn" />
......@@ -590,14 +615,8 @@ entityID="http://auth.idp.com/saml/metadata">
urn:oasis:names:tc:SAML:2.0:nameid-format:entity</NameIDFormat>
<NameIDFormat>
urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://auth.idp.com/saml/singleSignOn" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.idp.com/saml/singleSignOn" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://auth.idp.com/saml/singleSignOnArtifact" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.idp.com/saml/singleSignOnSOAP" />
</IDPSSODescriptor>
<SPSSODescriptor AuthnRequestsSigned="true"
WantAssertionsSigned="true"
......@@ -636,11 +655,6 @@ entityID="http://auth.idp.com/saml/metadata">
<ArtifactResolutionService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.idp.com/saml/artifact" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="http://auth.idp.com/saml/proxySingleLogoutSOAP" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="http://auth.idp.com/saml/proxySingleLogout"
ResponseLocation="http://auth.idp.com/saml/proxySingleLogoutReturn" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.idp.com/saml/proxySingleLogout"
ResponseLocation="http://auth.idp.com/saml/proxySingleLogoutReturn" />
......@@ -659,9 +673,6 @@ entityID="http://auth.idp.com/saml/metadata">
<AssertionConsumerService isDefault="true" index="0"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://auth.idp.com/saml/proxySingleSignOnPost" />
<AssertionConsumerService isDefault="false" index="1"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="http://auth.idp.com/saml/proxySingleSignOnArtifact" />
</SPSSODescriptor>
<AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
......
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