From b57d76c0ce6bee6b2b58e63ffff0fbb25dcb8c9e Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Thu, 15 Dec 2016 21:22:15 +0000 Subject: [PATCH] SAML in (big) progress (#595) --- .../lib/Lemonldap/NG/Portal/Auth/SAML.pm | 4 +- .../lib/Lemonldap/NG/Portal/Issuer/SAML.pm | 22 +++-------- .../lib/Lemonldap/NG/Portal/Lib/SAML.pm | 8 ++-- .../lib/Lemonldap/NG/Portal/Main/Run.pm | 5 +++ ...-Auth-and-issuer-SAML-POST-IdP-initiated.t | 1 + .../t/30-Auth-and-issuer-SAML-POST.t | 38 ++++++++++++++++++- .../t/30-Auth-and-issuer-SAML-Redirect.t | 34 ++++++++++++++++- 7 files changed, 85 insertions(+), 27 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm index a78c1e710..128e38b6b 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm @@ -875,7 +875,7 @@ sub extractFormInfo { . $req->param("url") . "\" />" . "\n"; - $self->info($html); + $self->info( $req, $html ); $req->datas->{login} = 1; return PE_CONFIRM; @@ -1282,7 +1282,7 @@ sub authLogout { # Set signature my $signSLOMessage = $self->conf->{samlIDPMetaDataOptions}->{$idpConfKey} - ->{samlIDPMetaDataOptionsSignSLOMessage}; + ->{samlIDPMetaDataOptionsSignSLOMessage} // 0; # Build Logout Request my $logout = diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm index f8b5c94c7..5f3114693 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm @@ -884,7 +884,7 @@ sub run { # TODO: replace this #$self->info( "

" . $self->msg(PM_CDC_WRITER) . "

" ); - $self->info($cdc_iframe); + $self->info( $req, $cdc_iframe ); } # HTTP-REDIRECT @@ -1083,7 +1083,7 @@ sub run { # Prepare logout on all others SP my $provider_nb = - $self->sendLogoutRequestToProviders( $logout, $relayID ); + $self->sendLogoutRequestToProviders( $req, $logout, $relayID ); # Decrypt session index my $local_session_id = @@ -1123,18 +1123,8 @@ sub run { # If no waiting SP, return directly SLO response unless ($provider_nb) { - if ( - my $tmp = $self->sendLogoutResponseToServiceProvider( - $logout, $method - ) - ) - { - return $tmp; - } - else { - $self->lmLog( "Fail to send SLO response", 'error' ); - return $self->sendSLOErrorResponse( $logout, $method ); - } + return $self->sendLogoutResponseToServiceProvider( $req, + $logout, $method ); } # Else build SLO status relay URL and display info @@ -1463,8 +1453,8 @@ sub logout { # providers during HTTP-REDIRECT process, return PE_INFO to notify to wait # for them. # Redirect on logout page when all is done. - if ( $self->sendLogoutRequestToProviders($logout) ) { - $self->{urldc} = $ENV{SCRIPT_NAME} . "?logout=1"; + if ( $self->sendLogoutRequestToProviders( $req, $logout ) ) { + $self->{urldc} = $req->scriptname . "?logout=1"; return PE_INFO; } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm index 3c5b67170..a1d7a8b83 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm @@ -2309,7 +2309,6 @@ sub sendLogoutResponseToServiceProvider { $self->lmLog( "Redirect user to $slo_url", 'debug' ); - die 'TODO: autoRedirect must not be called now'; return PE_REDIRECT; } @@ -2323,13 +2322,12 @@ sub sendLogoutResponseToServiceProvider { # TODO: insert postUrl in $req $req->postUrl($slo_url); - $req->datas->{postFields} = { 'SAMLResponse' => $slo_body }; + $req->{postFields} = { 'SAMLResponse' => $slo_body }; # RelayState - $req->datas->{postFields}->{'RelayState'} = $relaystate + $req->{postFields}->{'RelayState'} = $relaystate if ($relaystate); - die 'autoPost must not be called here'; $req->steps( ['autoPost'] ); return PE_OK; } @@ -2644,7 +2642,7 @@ sub sendLogoutRequestToProviders { $info .= ''; # Print some information to the user. - $self->info($info) if $providersCount; + $self->p->info( $req, $info ) if $providersCount; return $providersCount; } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm index 4089eda66..936970440 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm @@ -582,4 +582,9 @@ sub getFirstValue { return $values[0]; } +sub info { + my($self,$req,$info)=@_; + print STDERR "####### TODO: info()\n"; +} + 1; diff --git a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t index f04081ab9..4718745da 100644 --- a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t +++ b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t @@ -447,6 +447,7 @@ sub sp { samlIDPMetaDataOptionsEncryptionMode => 'none', samlIDPMetaDataOptionsSSOBinding => 'POST', samlIDPMetaDataOptionsSLOBinding => 'POST', + samlIDPMetaDataOptionsSignSLOMessage => 0, samlIDPMetaDataOptionsAllowLoginFromIDP => 1, } }, diff --git a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST.t b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST.t index afd4c9e78..05cfa93ed 100644 --- a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST.t +++ b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-POST.t @@ -7,8 +7,8 @@ BEGIN { require 't/test-lib.pm'; } -my $maintests = 33; -my $debug = 'debug'; +my $maintests = 39; +my $debug = 'error'; my ( $issuer, $sp, $res ); my %handlerOR = ( issuer => [], sp => [] ); @@ -222,6 +222,40 @@ SKIP: { ); ok( $res->[0] == 200, 'Return code is 200' ); + # Get SAML response + ok( + $res->[2]->[0] =~ + /[2], + ' _post( + $url, IO::String->new($s), + accept => 'text/html', + length => length($s), + cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata', + ), + 'Post SAML response to SP' + ); + ok( $res->[0] == 302, 'Get redirection' ); + ok( $sp->getRedirection($res) eq 'http://auth.sp.com', 'Redirection points to SP'); + #print STDERR Dumper($res); } diff --git a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Redirect.t b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Redirect.t index d3abf2565..8fa8f0f63 100644 --- a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Redirect.t +++ b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Redirect.t @@ -7,8 +7,8 @@ BEGIN { require 't/test-lib.pm'; } -my $maintests = 32; -my $debug = 'debug'; +my $maintests = 37; +my $debug = 'error'; my ( $issuer, $sp, $res ); my %handlerOR = ( issuer => [], sp => [] ); @@ -209,6 +209,36 @@ SKIP: { ), 'Launch SAML logout request to IdP' ); + ok( $res->[0] == 302, 'Return code is 302' ); + ok( $url = $sp->getRedirection($res), 'Get location header' ) + or explain( + $res->[1], +'Location: http://auth.sp.com/saml/proxySingleLogoutReturn?SAMLResponse=...' + ); + ok( + $url =~ +m#^http://auth.sp.com/saml/proxySingleLogoutReturn\?SAMLResponse=(.+)#, + 'Redirection points to SP with SAML response' + ) + or explain( + $res->[1], +'Location: http://auth.sp.com/saml/proxySingleLogoutReturn?SAMLResponse=...' + ); + $url =~ m#^http://auth.sp.com(.+?)\?(.+)$#; + $url = $1; + $query = $2; + + # Send SAML response to SP + switch ('sp'); + ok( + $res = $sp->_get( + $url, + query => $query, + accept => 'text/html', + ), + 'Launch SAML logout request to IdP' + ); + ok( $res->[0] == 200, 'Return code is 200' ) or explain( $res->[0], 200 ); #print STDERR Dumper($res); }