Commit 7eefc6af authored by Clément OUDOT's avatar Clément OUDOT
Browse files

SAML: manage SOAP

parent 0c833944
......@@ -422,6 +422,9 @@ sub extractFormInfo {
# Create Logout object
$logout = $self->createLogout($server);
# Get relayState
$relaystate = $self->param('RelayState');
# 1.2.1 HTTP-REDIRECT
if ( $request_method =~ /^GET$/ ) {
......@@ -619,8 +622,12 @@ sub extractFormInfo {
$self->{urldc} = $slo_url;
$self->{error} = $self->_subProcess(qw(autoRedirect));
return $self->{error};
$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
......@@ -630,11 +637,14 @@ sub extractFormInfo {
my $slo_url = $logout->msg_url;
my $slo_body = $logout->msg_body;
# TODO relayState ?
$self->{postUrl} = $slo_url;
$self->{postFields} = { 'SAMLResponse' => $slo_body };
# RelayState
$self->{postFields} =
{ $self->{postFields}, 'RelayState' => $relaystate }
if ($relaystate);
$self->_subProcess(qw(autoPost));
# If we are here, there was a problem with POST response
......@@ -775,9 +785,17 @@ sub extractFormInfo {
}
# 3. Build authentication request
# Force HTTP-REDIRECT method
# TODO choose method depending on IDP
$method = Lasso::Constants::HTTP_METHOD_REDIRECT;
# IDP entityID
$self->{_idp} = $idp;
my $IDPentityID = $self->{_idpList}->{$idp}->{entityID};
$login = $self->createAuthnRequest( $server, $IDPentityID );
# Create SSO request
$login = $self->createAuthnRequest( $server, $IDPentityID, $method );
unless ($login) {
$self->lmLog( "Could not create authentication request on $IDPentityID",
......@@ -807,16 +825,46 @@ sub extractFormInfo {
'debug'
);
# Redirect user to IDP SSO URL
# Replace urldc value by SSO URL value and call sub autoRedirect
# TODO Manage other transport (POST, SOAP, ...)
# Send SSO request depending on request method
# HTTP-REDIRECT
if ( $method == Lasso::Constants::HTTP_METHOD_REDIRECT ) {
# Redirect user to response URL
my $sso_url = $login->msg_url;
$self->lmLog( "Redirect user to $sso_url", 'debug' );
$self->{urldc} = $sso_url;
$self->{error} = $self->_subProcess(qw(autoRedirect));
return $self->{error};
$self->_subProcess(qw(autoRedirect));
# If we are here, there was a problem with GET request
$self->lmLog( "SSO request was not sent trough GET", 'error' );
return PE_ERROR;
}
# HTTP-POST
if ( $method == Lasso::Constants::HTTP_METHOD_POST ) {
# Use autosubmit form
my $sso_url = $login->msg_url;
my $sso_body = $login->msg_body;
$self->{postUrl} = $sso_url;
$self->{postFields} = { 'SAMLRequest' => $sso_body };
# RelayState
$self->{postFields} =
{ $self->{postFields}, 'RelayState' => $login->msg_relayState }
if ( $login->msg_relayState );
$self->_subProcess(qw(autoPost));
# If we are here, there was a problem with POST request
$self->lmLog( "SSO request was not sent trough POST", 'error' );
return PE_ERROR;
}
# No SOAP transport for SSO request
}
## @apmethod int setAuthSessionInfo()
......@@ -922,8 +970,12 @@ sub authLogout {
return PE_ERROR;
}
# Force SOAP method
# TODO choose method depending on IDP
$method = Lasso::Constants::HTTP_METHOD_SOAP;
# Build Logout Request
my $logout = $self->createLogoutRequest( $server, $session_dump );
my $logout = $self->createLogoutRequest( $server, $session_dump, $method );
unless ($logout) {
$self->lmLog( "Could not create logout request", 'error' );
return PE_ERROR;
......@@ -951,10 +1003,6 @@ sub authLogout {
'debug'
);
# Force HTTP-REDIRECT method
# TODO choose method depending on IDP
$method = Lasso::Constants::HTTP_METHOD_REDIRECT;
# Send request depending on request method
# HTTP-REDIRECT
if ( $method == Lasso::Constants::HTTP_METHOD_REDIRECT ) {
......@@ -989,9 +1037,32 @@ sub authLogout {
my $slo_url = $logout->msg_url;
my $slo_body = $logout->msg_body;
$self->lmLog( "SOAP request $slo_body", 'debug' );
# Send SOAP request and manage response
my $response = $self->sendSOAPMessage( $slo_url, $slo_body );
# Create Logout object
$logout = $self->createLogout($server);
# Process logout response
my $result = $self->processLogoutResponseMsg( $logout, $response );
unless ($result) {
$self->lmLog( "Fail to process logout response", 'error' );
return PE_ERROR;
}
$self->lmLog( "Logout response is valid", 'debug' );
# Replay protection
my $samlID = $logout->response()->InResponseTo;
unless ( $self->replayProtection($samlID) ) {
# Logout request was already consumed or is expired
$self->lmLog( "Message $samlID already used or expired", 'error' );
return PE_ERROR;
}
# TODO send SOAP request and manage response
return;
}
......
......@@ -835,16 +835,18 @@ sub controlExistingSession {
}
# Call issuerDB logout
eval { $self->_sub('issuerLogout'); };
eval { $self->{error} = $self->_sub('issuerLogout'); };
if ($@) {
$self->lmLog( "Error when calling issuerLogout: $@", 'debug' );
}
return $self->{error} if $self->{error};
# Call authentication logout
eval { $self->_sub('authLogout'); };
eval { $self->{error} = $self->_sub('authLogout'); };
if ($@) {
$self->lmLog( "Error when calling authLogout: $@", 'debug' );
}
return $self->{error} if $self->{error};
# Redirect or Post if asked by authLogout
$self->_subProcess(qw(autoRedirect)) if ( $self->{urldc} );
......
......@@ -22,7 +22,7 @@ our @EXPORT = qw(
createLogoutRequest createLogout initLogoutRequest buildLogoutRequestMsg
setSessionFromDump getMetaDataURL processLogoutResponseMsg processLogoutRequestMsg
validateLogoutRequest buildLogoutResponseMsg replayProtection
resolveArtifact processArtResponseMsg
resolveArtifact processArtResponseMsg sendSOAPMessage
);
our $VERSION = '0.01';
......@@ -161,7 +161,6 @@ sub addIDP {
return 0 unless ( $server->isa("Lasso::Server") and defined $metadata );
no strict 'subs';
return $self->addProvider( $server, Lasso::Constants::PROVIDER_ROLE_IDP,
$metadata, $public_key, $ca_cert_chain );
}
......@@ -226,13 +225,14 @@ sub getOrganizationName {
return $data->{OrganizationName}->{content};
}
## @method Lasso::Login createAuthnRequest(Lasso::Server server, string idp)
## @method Lasso::Login createAuthnRequest(Lasso::Server server, string idp, int method)
# Create authentication request for selected IDP
# @param Lasso::Server server
# @param string entityID
# @param server Lasso::Server object
# @param entityID IDP entityID
# @param method HTTP method
# @return Lasso::Login object
sub createAuthnRequest {
my ( $self, $server, $idp ) = splice @_;
my ( $self, $server, $idp, $method ) = splice @_;
# Create Lasso Login
my $login = $self->createLogin($server);
......@@ -242,9 +242,8 @@ sub createAuthnRequest {
return;
}
# Get HTTP method for selected IDP
my $method = $self->getHttpMethod( $server, $idp );
# Default method: HTTP REDIRECT
$method = Lasso::Constants::HTTP_METHOD_REDIRECT unless defined $method;
$self->lmLog( "Use HTTP method $method", 'debug' );
# Init authentication request
......@@ -264,6 +263,7 @@ sub createAuthnRequest {
$self->lmLog( "Set $relaystate in RelayState", 'debug' );
# Customize request
# TODO Get customization parameters from IDP configuration
my $request = $login->request();
$request->NameIDPolicy()
->Format(Lasso::Constants::SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT);
......@@ -316,7 +316,6 @@ sub getHttpMethod {
# TODO
# By default, use HTTP REDIRECT
no strict 'subs';
return Lasso::Constants::HTTP_METHOD_REDIRECT;
}
......@@ -584,24 +583,25 @@ sub validateConditions {
return 1;
}
## @method Lasso::Logout createLogoutRequest(Lasso::Server server, string session_dump)
## @method Lasso::Logout createLogoutRequest(Lasso::Server server, string session_dump, int method)
# Create logout request for selected entity
# @param server Lasso::Server object
# @param session_dump Lasso::Session dump
# @param method HTTP method
# @return Lasso::Login object
sub createLogoutRequest {
my ( $self, $server, $session_dump ) = splice @_;
my ( $self, $server, $session_dump, $method ) = splice @_;
my $session;
# Create Lasso Logout
my $logout = $self->createLogout($server);
# TODO Choose HTTP method
my $method = Lasso::Constants::HTTP_METHOD_REDIRECT;
# Default method: SOAP
$method = Lasso::Constants::HTTP_METHOD_SOAP unless defined $method;
$self->lmLog( "Use HTTP method $method", 'debug' );
unless ( $self->setSessionFromDump( $logout, $session_dump ) ) {
$self->lmLog( "Could fill Lasso::Logout with session dump", 'error' );
$self->lmLog( "Could not fill Lasso::Logout with session dump", 'error' );
return;
}
......@@ -860,6 +860,35 @@ sub processArtResponseMsg {
return 0;
}
## @method string sendSOAPMessage(string endpoint, string message)
# Send SOAP message and get response
# @param endpoint SOAP End Point
# @param message SOAP message
# @return SOAP response
sub sendSOAPMessage {
my ( $self, $endpoint, $message ) = splice @_;
my $response;
# LWP User Agent
my $ua = new LWP::UserAgent;
push @{ $ua->requests_redirectable }, 'POST';
my $request = HTTP::Request->new( 'POST' => $endpoint );
$request->content_type('text/xml');
$request->content($message);
$self->lmLog( "Send SOAP message $message to $endpoint", 'debug' );
# SOAP call
my $soap_answer = $ua->request($request);
if ( $soap_answer->code() == "200" ) {
$response = $soap_answer->content();
$self->lmLog( "Get response $response", 'debug' );
}
return $response;
}
1;
__END__
......@@ -1018,6 +1047,10 @@ Resolve artifact to get the real SAML message
Process artifact response message
=head2 sendSOAPMessage
Send SOAP message and get response
=head1 SEE ALSO
L<Lemonldap::NG::Portal::AuthSAML>, L<Lemonldap::NG::Portal::UserDBSAML>
......
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