SAML: first work on dispatching logout requests to SP during IDP SLO process
This commit is contained in:
parent
c387e47e4f
commit
cd8b59998b
@ -6,6 +6,7 @@
|
|||||||
package Lemonldap::NG::Portal::IssuerDBSAML;
|
package Lemonldap::NG::Portal::IssuerDBSAML;
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
|
use Lemonldap::NG::Common::Conf::SAML::Metadata;
|
||||||
use Lemonldap::NG::Portal::Simple;
|
use Lemonldap::NG::Portal::Simple;
|
||||||
use Lemonldap::NG::Portal::_SAML;
|
use Lemonldap::NG::Portal::_SAML;
|
||||||
our @ISA = qw(Lemonldap::NG::Portal::_SAML);
|
our @ISA = qw(Lemonldap::NG::Portal::_SAML);
|
||||||
@ -671,39 +672,7 @@ sub issuerForAuthUser {
|
|||||||
|
|
||||||
$self->lmLog( "SLO: Logout request is valid", 'debug' );
|
$self->lmLog( "SLO: Logout request is valid", 'debug' );
|
||||||
|
|
||||||
# Get EntityID
|
$self->sendLogoutRequestToServiceProviders($logout);
|
||||||
my $entityID = $logout->request->Issuer->content;
|
|
||||||
|
|
||||||
$self->lmLog( "Request issued from $entityID", 'debug' );
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# Get all entityID into the current session, to send logout
|
|
||||||
# requests on all of them.
|
|
||||||
my @entitiesID = $session =~ /RemoteProviderID="[^"]+"/g;
|
|
||||||
@entitiesID = map {
|
|
||||||
my $id = $_;
|
|
||||||
$id =~ s/RemoteProviderID="([^"]+)"/$1/;
|
|
||||||
$id;
|
|
||||||
} @entitiesID;
|
|
||||||
|
|
||||||
# Foreach SP found in session, get it from configuration,
|
|
||||||
# and send the appropriate logout request (HTTP,POST,SOAP).
|
|
||||||
foreach (@entitiesID) {
|
|
||||||
|
|
||||||
# Do not process logout on SP that initiate the
|
|
||||||
# logout request
|
|
||||||
next if ($entityID =~ /^$_$/);
|
|
||||||
|
|
||||||
# Find EntityID in SPList
|
|
||||||
unless ( defined $self->{_spList}->{$entityID} ) {
|
|
||||||
$self->lmLog(
|
|
||||||
"$entityID does not match any known SP", 'error' );
|
|
||||||
return PE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
$self->lmLog( "Initiate logout request on $_", 'debug' );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Validate request if no previous error
|
# Validate request if no previous error
|
||||||
unless ( $self->validateLogoutRequest($logout) ) {
|
unless ( $self->validateLogoutRequest($logout) ) {
|
||||||
@ -831,6 +800,137 @@ sub sendLogoutResponseAfterLogoutRequest {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub sendLogoutRequestToServiceProviders {
|
||||||
|
my $self = shift;
|
||||||
|
my $logout = shift;
|
||||||
|
my $server = $self->{_lassoServer};
|
||||||
|
|
||||||
|
# Get EntityID
|
||||||
|
my $entityID = $logout->request->Issuer->content;
|
||||||
|
|
||||||
|
# Reset providerID into Lasso::Logout object
|
||||||
|
$self->resetProviderIdIndex($logout);
|
||||||
|
|
||||||
|
# Page header
|
||||||
|
print $self->header();
|
||||||
|
print $self->start_html();
|
||||||
|
print '<ul>';
|
||||||
|
|
||||||
|
# Foreach SP found in session, get it from configuration, and send the
|
||||||
|
# appropriate logout request (HTTP,POST,SOAP).
|
||||||
|
while ( my $providerID = $self->getNextProviderId($logout) ) {
|
||||||
|
|
||||||
|
# Do not process logout on SP that initiate the logout request
|
||||||
|
next if ($entityID =~ /^$providerID$/);
|
||||||
|
|
||||||
|
# Find EntityID in SPList
|
||||||
|
unless ( defined $self->{_spList}->{$providerID} ) {
|
||||||
|
$self->lmLog( "$entityID does not match any known SP", 'error' );
|
||||||
|
return PE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get first HTTP method
|
||||||
|
my $protocolType = Lasso::Constants::MD_PROTOCOL_TYPE_SINGLE_LOGOUT;
|
||||||
|
my $method =
|
||||||
|
$self->getFirstHttpMethod( $server, $providerID, $protocolType );
|
||||||
|
|
||||||
|
# Initiate the logout request
|
||||||
|
unless ( $self->initLogoutRequest( $logout, $providerID, $method ) )
|
||||||
|
{
|
||||||
|
$self->lmLog( "Initiate logout request failed for $providerID",
|
||||||
|
'error' );
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build request message
|
||||||
|
unless ( $self->buildLogoutRequestMsg( $logout ) )
|
||||||
|
{
|
||||||
|
$self->lmLog( "Build logout request failed for $providerID",
|
||||||
|
'error' );
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Send logout request to the provider depending of the request method
|
||||||
|
# HTTP-REDIRECT
|
||||||
|
if ( $method == Lasso::Constants::HTTP_METHOD_REDIRECT ) {
|
||||||
|
|
||||||
|
# Redirect user to response URL
|
||||||
|
my $slo_url = $logout->msg_url;
|
||||||
|
|
||||||
|
print '<li>' . $providerID . '...'
|
||||||
|
. '<iframe src="' . $slo_url . '" alt="" marginwidth="0"'
|
||||||
|
. 'marginheight="0" scrolling="no" style="border: none"'
|
||||||
|
. ' width="12" height="12">'
|
||||||
|
. '<img src="' . $slo_url . '" width="12" height="12"></img>'
|
||||||
|
. '</iframe></li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTP-POST
|
||||||
|
if ( $method == Lasso::Constants::HTTP_METHOD_POST ) {
|
||||||
|
|
||||||
|
# Use autosubmit form
|
||||||
|
my $slo_url = $logout->msg_url;
|
||||||
|
my $slo_body = $logout->msg_body;
|
||||||
|
|
||||||
|
#$self->{postUrl} = $slo_url;
|
||||||
|
#$self->{postFields} = { 'SAMLResponse' => $slo_body };
|
||||||
|
|
||||||
|
# RelayState
|
||||||
|
#$self->{postFields}->{'RelayState'} = $relaystate
|
||||||
|
#if ($relaystate);
|
||||||
|
|
||||||
|
$self->lmLog( "POST method not yet available", 'debug' );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTP-SOAP
|
||||||
|
if ( $method == Lasso::Constants::HTTP_METHOD_SOAP ) {
|
||||||
|
|
||||||
|
my $slo_url = $logout->msg_url;
|
||||||
|
my $slo_body = $logout->msg_body;
|
||||||
|
|
||||||
|
# Send SOAP request and manage response
|
||||||
|
my $sp_response = $self->sendSOAPMessage( $slo_url, $slo_body );
|
||||||
|
|
||||||
|
unless ($sp_response) {
|
||||||
|
$self->lmLog( "No logout response to SOAP request", 'error' );
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create Logout object
|
||||||
|
my $sp_logout = $self->createLogout($server);
|
||||||
|
|
||||||
|
# Process logout response
|
||||||
|
my $sp_result =
|
||||||
|
$self->processLogoutResponseMsg( $sp_logout, $sp_response );
|
||||||
|
|
||||||
|
unless ($sp_result) {
|
||||||
|
$self->lmLog( "Fail to process logout response", 'error' );
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->lmLog( "Logout response is valid", 'debug' );
|
||||||
|
|
||||||
|
# Replay protection
|
||||||
|
my $samlID = $sp_logout->response()->InResponseTo;
|
||||||
|
|
||||||
|
unless ( $self->replayProtection($samlID) ) {
|
||||||
|
|
||||||
|
# Logout request was already consumed or is expired
|
||||||
|
$self->lmLog( "Message $samlID already used or expired", 'error' );
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# End page
|
||||||
|
print '</ul>';
|
||||||
|
print $self->end_html();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
__END__
|
__END__
|
||||||
|
@ -577,6 +577,37 @@ sub getOrganizationName {
|
|||||||
return $data->{OrganizationName}->{content};
|
return $data->{OrganizationName}->{content};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## @method string getNextProviderId(Lasso::Logout logout)
|
||||||
|
# Returns the provider id from providerID_index in list of providerIDs in
|
||||||
|
# principal session with the exception of initial service provider ID.
|
||||||
|
# @param logout Lasso::Logout object
|
||||||
|
# @return string
|
||||||
|
sub getNextProviderId {
|
||||||
|
my $self = shift;
|
||||||
|
my $logout = shift;
|
||||||
|
my $providerId;
|
||||||
|
|
||||||
|
eval { $providerId = Lasso::Logout::get_next_providerID($logout); };
|
||||||
|
if ($@) {
|
||||||
|
$self->checkLassoError($@);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method boolean resetProviderIdIndex(Lasso::Logout logout)
|
||||||
|
# Reset the providerID_index attribute in Lasso::Logout object
|
||||||
|
# @param logout Lasso::Logout object
|
||||||
|
# @return boolean
|
||||||
|
sub resetProviderIdIndex {
|
||||||
|
my $self = shift;
|
||||||
|
my $logout = shift;
|
||||||
|
|
||||||
|
eval { Lasso::Logout::reset_providerID_index($logout); };
|
||||||
|
return $self->checkLassoError($@);
|
||||||
|
}
|
||||||
|
|
||||||
## @method Lasso::Login createAuthnRequest(Lasso::Server server, string idp, int method, boolean forceAuthn, boolean isPassive, string nameIDFormat, boolean allowProxiedAuthn, boolean signSSOMessage, string requestedAuthnContext)
|
## @method Lasso::Login createAuthnRequest(Lasso::Server server, string idp, int method, boolean forceAuthn, boolean isPassive, string nameIDFormat, boolean allowProxiedAuthn, boolean signSSOMessage, string requestedAuthnContext)
|
||||||
# Create authentication request for selected IDP
|
# Create authentication request for selected IDP
|
||||||
# @param server Lasso::Server object
|
# @param server Lasso::Server object
|
||||||
|
Loading…
Reference in New Issue
Block a user