From 439dc6dcfbbaf824a7452cbe02f22536ed29bea2 Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Sun, 18 Dec 2016 08:07:48 +0000 Subject: [PATCH] SOAP SLO response OK for Auth/SAML (#595) --- .../lib/Lemonldap/NG/Portal/Auth/Base.pm | 2 +- .../lib/Lemonldap/NG/Portal/Auth/SAML.pm | 25 +++++++------ .../lib/Lemonldap/NG/Portal/Lib/SAML.pm | 35 +++++++++++++++++++ .../lib/Lemonldap/NG/Portal/Main/Constants.pm | 5 ++- .../lib/Lemonldap/NG/Portal/Main/Process.pm | 2 +- .../lib/Lemonldap/NG/Portal/Main/Request.pm | 3 ++ .../lib/Lemonldap/NG/Portal/Main/Run.pm | 3 ++ ...-Auth-and-issuer-SAML-POST-IdP-initiated.t | 12 +++---- 8 files changed, 65 insertions(+), 22 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/Base.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/Base.pm index 21a462a25..221724210 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/Base.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/Base.pm @@ -5,7 +5,7 @@ use Mouse; our $VERSION = '2.0.0'; -extends 'Lemonldap::NG::Common::Module'; +extends 'Lemonldap::NG::Portal::Main::Plugin'; # PROPERTIES 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 128e38b6b..2152e4088 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm @@ -18,6 +18,7 @@ use Lemonldap::NG::Portal::Main::Constants qw( PE_SAML_SLO_ERROR PE_SAML_SSO_ERROR PE_SAML_UNKNOWN_ENTITY + PE_SENDRESPONSE ); use Lemonldap::NG::Common::Conf::SAML::Metadata; @@ -599,7 +600,7 @@ sub extractFormInfo { my $real_session = $sessionInfo->data->{_saml_id}; my $ssoSession = - $self->getApacheSession( $real_session, 1 ); + $self->p->getApacheSession( $real_session, 1 ); # Get Lasso::Session dump # This value is erased if a next session match the SLO request @@ -616,7 +617,7 @@ sub extractFormInfo { # Delete real session my $del_real_result = - $self->_deleteSession($ssoSession); + $self->p->_deleteSession( $req, $ssoSession ); $self->lmLog( "Delete real session $real_session result: $del_real_result", @@ -738,16 +739,18 @@ sub extractFormInfo { $self->lmLog( "SOAP response $slo_body", 'debug' ); - $req->datas->{SOAPMessage} = $slo_body; - - # TODO: check this - $req->steps( ['returnSOAPMessage'] ); - return PE_OK; + $req->response( + [ + 200, + [ + 'Content-Type' => 'application/xml', + 'Content-Length' => length($slo_body) + ], + [$slo_body] + ] + ); - # If we are here, there was a problem with SOAP response - $self->lmLog( "Logout response was not sent trough SOAP", - 'error' ); - return PE_SAML_SLO_ERROR; + return PE_SENDRESPONSE; } } 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 a1d7a8b83..f32d5d1dd 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm @@ -1460,6 +1460,41 @@ sub getMetaDataURL { return $uri->path(); } +sub getRouteFromMetaDataURL { + my ( $self, $key, $index, $sub ) = @_; + my $uri = $self->getMetaDataURL( $key, $index, 0 ); + unless ( $uri =~ m#^/\w# ) { + $self->lmLog( "$key has no index $index", 'debug' ); + return undef; + } + my @t = grep /\w/, split( /\//, $uri ); + my $h = { pop(@t) => $sub }; + while ( my $s = pop @t ) { + $h = { $s => $h }; + } + return %$h; +} + +sub addRouteFormMetaDataURL { + my ( $self, @args ) = @_; + $self->addAuthRouteFormMetaDataURL(@args); + $self->addUnauthRouteFormMetaDataURL(@args); +} + +sub addAuthRouteFormMetaDataURL { + my ( $self, $key, $index, $sub, $methods ) = @_; + my %route = $self->getRouteFromMetaDataURL( $key, $index, $sub ); + return unless (%route); + $self->addAuthRoute( %route, $methods ); +} + +sub addUnauthRouteFormMetaDataURL { + my ( $self, $key, $index, $sub, $methods ) = @_; + my %route = $self->getRouteFromMetaDataURL( $key, $index, $sub ); + return unless (%route); + $self->addUnauthRoute( %route, $methods ); +} + ## @method boolean processLogoutResponseMsg(Lasso::Logout logout, string response) # Process logout response message # @param logout Lasso::Logout object diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Constants.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Constants.pm index 6b351d469..3665e18ea 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Constants.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Constants.pm @@ -9,8 +9,7 @@ use constant { # Portal errors # Developers warning, do not use PE_INFO, it's reserved to autoRedirect. # If you want to send an information, use $self->info('text'). - PE_IMG_NOK => -5, - PE_IMG_OK => -4, + PE_SENDRESPONSE => -4, PE_INFO => -3, PE_REDIRECT => -2, PE_DONE => -1, @@ -122,7 +121,7 @@ use constant { }; # EXPORTER PARAMETERS -our @EXPORT_OK = qw( PE_IMG_NOK PE_IMG_OK PE_INFO PE_REDIRECT PE_DONE PE_OK +our @EXPORT_OK = qw( PE_SENDRESPONSE PE_INFO PE_REDIRECT PE_DONE PE_OK PE_SESSIONEXPIRED PE_FORMEMPTY PE_WRONGMANAGERACCOUNT PE_USERNOTFOUND PE_BADCREDENTIALS PE_LDAPCONNECTFAILED PE_LDAPERROR PE_APACHESESSIONERROR PE_FIRSTACCESS PE_BADCERTIFICATE PE_PP_ACCOUNT_LOCKED PE_PP_PASSWORD_EXPIRED diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm index 1d89d9ded..d90264fad 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Process.pm @@ -41,7 +41,7 @@ sub restoreArgs { my ( $self, $req ) = @_; $req->parseBody; $req->mustRedirect(1); - return ( %{ $req->params } ? PE_OK : PE_FORMEMPTY ); + return PE_OK; } sub importHandlerDatas { diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm index 592a83750..10f766a12 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Request.pm @@ -41,6 +41,9 @@ has user => ( is => 'rw' ); # Response cookies (list of strings built by cookie()) has respCookies => ( is => 'rw' ); +# Embedded response +has response => ( is => 'rw' ); + # Template to display (if not defined, login or menu) has template => ( is => 'rw' ); 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 869a089d8..3317f0867 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm @@ -124,6 +124,9 @@ sub do { my $err = $req->error( $self->process($req) ); # TODO: updateStatus + if ( $err == PE_SENDRESPONSE ) { + return $req->response; + } if ( !$self->conf->{noAjaxHook} and $req->wantJSON ) { if ( $err > 0 and !%{ $req->sessionInfo } ) { return [ 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 a647d79e2..40cecd299 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 @@ -148,18 +148,18 @@ sub LWP::UserAgent::request { ), 'Execute request' ); - #ok( ( $res->[0] == 200 or $res->[0] == 400 ), 'Response is 200 or 400' ) - # or explain( $res->[0], "200 or 400" ); - #ok( $issuer->getHeader( $res, 'Content-Type' ) =~ m#^application/xml#, - # 'Content is XML' ) - # or explain( $res->[1], 'Content-Type => application/xml' ); + ok( ( $res->[0] == 200 or $res->[0] == 400 ), 'Response is 200 or 400' ) + or explain( $res->[0], "200 or 400" ); + ok( $issuer->getHeader( $res, 'Content-Type' ) =~ m#^application/xml#, + 'Content is XML' ) + or explain( $res->[1], 'Content-Type => application/xml' ); my $httpResp = HTTP::Response->new( $res->[0], 'OK' ); while ( my $name = shift @{ $res->[1] } ) { $httpResp->header( $name, shift( @{ $res->[1] } ) ); } $httpResp->content( join( '', @{ $res->[2] } ) ); - count(2); + count(4); return $httpResp; } -- GitLab