SAML: manage logout into issuerForAuthUser

This commit is contained in:
Thomas CHEMINEAU 2010-04-20 15:31:21 +00:00
parent 005037df8c
commit 6bfdad2d0b

View File

@ -34,7 +34,6 @@ sub issuerDBInit {
sub issuerForUnAuthUser {
my $self = shift;
my $server = $self->{_lassoServer};
my $idp;
# Get configuration parameter
my $saml_sso_soap_url =
@ -56,14 +55,6 @@ sub issuerForUnAuthUser {
my $saml_ars_url = $self->getMetaDataURL(
"samlIDPSSODescriptorArtifactResolutionServiceArtifact");
# Try to recover IDP from IDP cookie
my %cookies = fetch CGI::Cookie;
my $idp_cookie = $cookies{ $self->{samlIdPResolveCookie} };
if ($idp_cookie) {
$idp = $idp_cookie->value;
$self->lmLog( "IDP $idp found in IDP resolution cookie", 'debug' );
}
# Get HTTP request informations to know
# if we are receving SAML request or response
my $url = $self->url();
@ -135,24 +126,6 @@ sub issuerForUnAuthUser {
# Create Logout object
my $logout = $self->createLogout($server);
# Do we check signature?
my $checkSLOMessageSignature;
if ($idp) {
$checkSLOMessageSignature =
$self->{samlIDPMetaDataOptions}->{$idp}
->{samlIDPMetaDataOptionsCheckSLOMessageSignature};
}
else {
$self->lmLog(
"IDP not found, disable checkSLOMessageSignature option",
'debug'
);
}
unless ($checkSLOMessageSignature) {
$self->lmLog( "Message signature will not be checked", 'debug' );
$self->disableSignatureVerification($logout);
}
# Check SAML Message
my ( $request, $response, $method, $relaystate, $artifact ) =
$self->checkMessage( $url, $request_method, $content_type, "logout" );
@ -174,96 +147,22 @@ sub issuerForUnAuthUser {
return PE_ERROR;
}
print STDERR $saml_request->dump() . "\n";
# Set RelayState
if ($relaystate) {
$logout->msg_relayState($relaystate);
$self->lmLog( "Set $relaystate in RelayState", 'debug' );
}
# Do we set signature?
if ($idp) {
my $signSLOMessage =
$self->{samlIDPMetaDataOptions}->{$idp}
->{samlIDPMetaDataOptionsSignSLOMessage};
unless ($signSLOMessage) {
$self->lmLog( "SLO message to IDP $idp will not be signed",
'debug' );
$self->disableSignature($logout);
}
}
else {
$self->lmLog(
"IDP not found, disable checkSLOMessageSignature option",
'debug'
);
}
# Logout response
unless ( $self->buildLogoutResponseMsg($logout) ) {
$self->lmLog( "Unable to build SLO response", 'error' );
return PE_ERROR;
}
print STDERR $logout->dump() . "\n";
# Send response depending on request method
# HTTP-REDIRECT
if ( $method == Lasso::Constants::HTTP_METHOD_REDIRECT ) {
# Redirect user to response URL
my $slo_url = $logout->msg_url;
$self->lmLog( "Redirect user to $slo_url", 'debug' );
$self->{urldc} = $slo_url;
$self->_subProcess(qw(autoRedirect));
# If we are here, there was a problem with GET request
$self->lmLog( "Logout response was not sent trough GET",
'error' );
return PE_ERROR;
}
# 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->_subProcess(qw(autoPost));
# If we are here, there was a problem with POST response
$self->lmLog( "Logout response was not sent trough POST",
'error' );
return PE_ERROR;
}
# HTTP-SOAP
if ( $method == Lasso::Constants::HTTP_METHOD_SOAP ) {
my $slo_body = $logout->msg_body;
$self->lmLog( "SOAP response $slo_body", 'debug' );
$self->{SOAPMessage} = $slo_body;
$self->_subProcess(qw(returnSOAPMessage));
# If we are here, there was a problem with SOAP response
$self->lmLog( "Logout response was not sent trough SOAP",
'error' );
return PE_ERROR;
}
# Send logout response
return PE_ERROR
unless ($self->sendLogoutResponseAfterLogoutRequest(
$logout, $method, $relaystate));
}
@ -725,6 +624,146 @@ sub issuerForAuthUser {
}
# 1.2. SLO
if ( $url =~
/^(\Q$saml_slo_soap_url\E|\Q$saml_slo_soap_url_ret\E|\Q$saml_slo_get_url\E|\Q$saml_slo_get_url_ret\E)$/i
)
{
$self->lmLog( "URL $url detected as an SLO URL", 'debug' );
# Create Logout object
my $logout = $self->createLogout($server);
# Check SAML Message
my ( $request, $response, $method, $relaystate, $artifact ) =
$self->checkMessage( $url, $request_method, $content_type, "logout" );
if ($request) {
# Load Session and Identity if they exist
my $session = $self->{sessionInfo}->{_lassoSessionDump};
my $identity = $self->{sessionInfo}->{_lassoIdentityDump};
if ($session) {
unless ( $self->setSessionFromDump( $logout, $session ) ) {
$self->lmLog( "Unable to load Lasso Session", 'error' );
return PE_ERROR;
}
$self->lmLog( "Lasso Session loaded", 'debug' );
}
if ($identity) {
unless ( $self->setIdentityFromDump( $logout, $identity ) ) {
$self->lmLog( "Unable to load Lasso Identity", 'error' );
return PE_ERROR;
}
$self->lmLog( "Lasso Identity loaded", 'debug' );
}
# Process logout request
unless ( $self->processLogoutRequestMsg( $logout, $request ) ) {
$self->lmLog( "SLO: Fail to process logout request", 'error' );
return PE_ERROR;
}
$self->lmLog( "SLO: Logout request is valid", 'debug' );
# Get EntityID
my $entityID = $logout->request->Issuer->content;
my $name_id = $logout->request()->NameID;
my $user = $name_id->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;
# Get corresponding session
my $local_sessions =
$self->{samlStorage}
->searchOn( $self->{samlStorageOptions}, "_user", $user, );
if ( my @local_sessions_keys = keys %$local_sessions ) {
my $session_dump;
my $logout_error = 0;
# A session was found
foreach (@local_sessions_keys) {
my $local_session = $_;
# Get session
$self->lmLog(
"Retrieve session $local_session for user $user",
'debug' );
my $sessionInfo =
$self->getApacheSession( $local_session, 1 );
# Get Lasso::Session dump
$session_dump = $sessionInfo->{_lassoSessionDump}
if $sessionInfo->{_lassoSessionDump};
# Delete Session
$self->lmLog(
"Delete session $local_session for user $user",
'debug' );
my $logout_result = $self->_deleteSession($sessionInfo);
$self->lmLog( "Local Logout result: $logout_result",
'debug' );
$logout_error = 1 unless $logout_result;
}
# Set session from dump
unless ( $self->setSessionFromDump( $logout, $session_dump ) ) {
$self->lmLog( "Cannot set session from dump in logout",
'error' );
$logout_error = 1;
}
}
else {
# No corresponding session found
$self->lmLog( "No local session found for user $user",
'debug' );
}
# Validate request if no previous error
unless ( $self->validateLogoutRequest($logout) ) {
$self->lmLog( "SLO request is not valid", 'error' );
}
# Set RelayState
if ($relaystate) {
$logout->msg_relayState($relaystate);
$self->lmLog( "Set $relaystate in RelayState", 'debug' );
}
# Logout response
unless ( $self->buildLogoutResponseMsg($logout) ) {
$self->lmLog( "Unable to build SLO response", 'error' );
return PE_ERROR;
}
# Send logout response
return PE_ERROR
unless ($self->sendLogoutResponseAfterLogoutRequest(
$logout, $method, $relaystate));
}
}
return PE_OK;
}
@ -739,6 +778,79 @@ sub issuerLogout {
PE_OK;
}
## @pmethod int sendLogoutResponseAfterLogoutRequest(Lasso::Logout $logout,
# int $method string $relaystate)
# Send logout response issue from a logout request.
# @param $logout Lasso Logout object
# @param $method Method to use
# @param $relaystate The relay state
# @return boolean False if failed.
sub sendLogoutResponseAfterLogoutRequest {
my $self = shift;
my $logout = shift;
my $method = shift;
my $relaystate = shift;
# Send response depending on request method
# HTTP-REDIRECT
if ( $method == Lasso::Constants::HTTP_METHOD_REDIRECT ) {
# Redirect user to response URL
my $slo_url = $logout->msg_url;
$self->lmLog( "Redirect user to $slo_url", 'debug' );
$self->{urldc} = $slo_url;
$self->_subProcess(qw(autoRedirect));
# If we are here, there was a problem with GET request
$self->lmLog( "Logout response was not sent trough GET", 'error' );
return 0;
}
# 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->_subProcess(qw(autoPost));
# If we are here, there was a problem with POST response
$self->lmLog( "Logout response was not sent trough POST", 'error' );
return 0;
}
# HTTP-SOAP
if ( $method == Lasso::Constants::HTTP_METHOD_SOAP ) {
my $slo_body = $logout->msg_body;
$self->lmLog( "SOAP response $slo_body", 'debug' );
$self->{SOAPMessage} = $slo_body;
$self->_subProcess(qw(returnSOAPMessage));
# If we are here, there was a problem with SOAP response
$self->lmLog( "Logout response was not sent trough SOAP", 'error' );
return 0;
}
return 1;
}
1;
__END__