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 434832bc4..35ecf2a40 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm @@ -32,6 +32,9 @@ has ssoAssConsumerRe => ( is => 'rw' ); has sloRe => ( is => 'rw' ); has artRe => ( is => 'rw' ); has catch => ( is => 'rw' ); +use constant sessionKind => 'SAML'; +use constant lsDump => '_lassoSessionDump'; +use constant liDump => '_lassoIdentityDump'; sub forAuthUser { 'handleAuthRequests' } @@ -322,7 +325,13 @@ sub extractFormInfo { Lemonldap::NG::Common::Apache::Session->searchOn( $self->amOpts, "ProxyID", $assertion_responded ); - if ( my @saml_sessions_keys = keys %$saml_sessions ) { + if ( + my @saml_sessions_keys = grep { + $saml_sessions->{$_}->{_session_kind} eq + $self->sessionKind + } keys %$saml_sessions + ) + { # Warning if more than one session found if ( $#saml_sessions_keys > 0 ) { @@ -562,7 +571,12 @@ sub extractFormInfo { Lemonldap::NG::Common::Apache::Session->searchOn( $self->amOpts, "_nameID", $name_id->dump ); - if ( my @local_sessions_keys = keys %$local_sessions ) { + if ( + my @local_sessions_keys = grep { + $local_sessions->{$_}->{_session_kind} eq $self->sessionKind + } keys %$local_sessions + ) + { # At least one session was found foreach (@local_sessions_keys) { @@ -602,13 +616,13 @@ sub extractFormInfo { # Get Lasso::Session dump # This value is erased if a next session match the SLO request if ( $ssoSession - && $ssoSession->data->{_lassoSessionDump} ) + && $ssoSession->data->{ $self->lsDump } ) { $self->logger->debug( "Get Lasso::Session dump from session $real_session" ); $session_dump = - $ssoSession->data->{_lassoSessionDump}; + $ssoSession->data->{ $self->lsDump }; } # Real session will be deleted after (see $req->steps... before) @@ -1149,8 +1163,8 @@ sub setAuthSessionInfo { my $identity = $login->get_identity; # Dump Lasso objects in session - $req->{sessionInfo}->{_lassoSessionDump} = $session->dump() if $session; - $req->{sessionInfo}->{_lassoIdentityDump} = $identity->dump() if $identity; + $req->{sessionInfo}->{ $self->lsDump } = $session->dump() if $session; + $req->{sessionInfo}->{ $self->liDump } = $identity->dump() if $identity; # Keep SAML Token in session my $store_samlToken = $self->conf->{samlIDPMetaDataOptions}->{$idpConfKey} @@ -1217,7 +1231,7 @@ sub authLogout { $self->deleteSAMLSecondarySessions($session_id); # Recover Lasso::Session dump - my $session_dump = $req->{sessionInfo}->{_lassoSessionDump}; + my $session_dump = $req->{sessionInfo}->{ $self->lsDump }; unless ($session_dump) { $self->userLogger->error("Could not get session dump from session"); 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 fe52419c0..7996ca52a 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm @@ -25,6 +25,9 @@ has ssoUrlRe => ( is => 'rw' ); has ssoUrlArtifact => ( is => 'rw' ); has ssoGetUrl => ( is => 'rw' ); +use constant sessionKind => 'ISAML'; +use constant lsDump => '_lassoSessionDumpI'; +use constant liDump => '_lassoIdentityDumpI'; # INTERFACE @@ -220,8 +223,8 @@ sub run { if ( $request or $idp_initiated ) { # Load Session and Identity if they exist - my $session = $req->{sessionInfo}->{_lassoSessionDump}; - my $identity = $req->{sessionInfo}->{_lassoIdentityDump}; + my $session = $req->{sessionInfo}->{ $self->lsDump }; + my $identity = $req->{sessionInfo}->{ $self->liDump }; if ($session) { unless ( $self->setSessionFromDump( $login, $session ) ) { @@ -812,14 +815,14 @@ sub run { # Update session $self->logger->debug("Save Lasso identity in session"); $self->updatePersistentSession( $req, - { _lassoIdentityDump => $login->get_identity->dump }, + { $self->liDump => $login->get_identity->dump }, undef, $session_id ); } if ( $login->is_session_dirty ) { $self->logger->debug("Save Lasso session in session"); $self->p->updateSession( $req, - { _lassoSessionDump => $login->get_session->dump }, + { $self->lsDump => $login->get_session->dump }, $session_id ); } @@ -1109,8 +1112,8 @@ sub soapSloServer { } # Load Session and Identity if they exist - my $session = $local_session->data->{_lassoSessionDump}; - my $identity = $local_session->data->{_lassoIdentityDump}; + my $session = $local_session->data->{ $self->lsDump }; + my $identity = $local_session->data->{ $self->liDump }; if ($session) { unless ( $self->setSessionFromDump( $logout, $session ) ) { @@ -1220,8 +1223,8 @@ sub logout { my $logout = $self->createLogout( $self->lassoServer ); # Load Session and Identity if they exist - my $session = $req->{sessionInfo}->{_lassoSessionDump}; - my $identity = $req->{sessionInfo}->{_lassoIdentityDump}; + my $session = $req->{sessionInfo}->{ $self->lsDump }; + my $identity = $req->{sessionInfo}->{ $self->liDump }; if ($session) { unless ( $self->setSessionFromDump( $logout, $session ) ) { @@ -1288,8 +1291,8 @@ sub sloRelaySoap { } # Load Session and Identity if they exist - my $session = $relayInfos->data->{_lassoSessionDump}; - my $identity = $relayInfos->data->{_lassoIdentityDump}; + my $session = $relayInfos->data->{ $self->lsDump }; + my $identity = $relayInfos->data->{ $self->liDump }; my $providerID = $relayInfos->data->{_providerID}; my $relayState = $relayInfos->data->{_relayState} // ''; my $spConfKey = $self->spList->{$providerID}->{confKey}; @@ -1458,8 +1461,8 @@ sub sloServer { "Get session id $local_session_id (from cookie)"); } if ( $req->{sessionInfo} ) { - $session = $req->{sessionInfo}->{_lassoSessionDump}; - $identity = $req->{sessionInfo}->{_lassoIdentityDump}; + $session = $req->{sessionInfo}->{ $self->lsDump }; + $identity = $req->{sessionInfo}->{ $self->liDump }; } unless ($session) { @@ -1472,8 +1475,8 @@ sub sloServer { } # Load Session and Identity if they exist - $session = $local_session->data->{_lassoSessionDump}; - $identity = $local_session->data->{_lassoIdentityDump}; + $session = $local_session->data->{ $self->lsDump }; + $identity = $local_session->data->{ $self->liDump }; # Import user datas in $req (for other "logout" subs) $req->id( $local_session->data->{_session_id} ); @@ -1665,7 +1668,12 @@ sub attributeServer { Lemonldap::NG::Common::Apache::Session->searchOn( $self->amOpts, "_nameID", $name_id->dump ); - if ( my @saml_sessions_keys = keys %$saml_sessions ) { + if ( + my @saml_sessions_keys = + grep { $saml_sessions->{$_}->{_session_kind} eq $self->sessionKind } + keys %$saml_sessions + ) + { # Warning if more than one session found if ( $#saml_sessions_keys > 0 ) { 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 cc9e76722..0eed17d64 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SAML.pm @@ -1656,10 +1656,17 @@ sub replayProtection { Lemonldap::NG::Common::Apache::Session->searchOn( $self->amOpts, "_assert_id", $samlID ); - if ( my @keys = keys %$sessions ) { + if ( + my @keys = + grep { $sessions->{$_}->{_session_kind} eq $self->sessionKind } + keys %$sessions + ) + { # A session was found foreach (@keys) { + next + unless ( $sessions->{$_}->{_session_kind} eq $self->sessionKind ); my $session = $_; my $result = 1; @@ -1780,7 +1787,12 @@ sub loadArtifact { Lemonldap::NG::Common::Apache::Session->searchOn( $self->amOpts, "_art_id", $id ); - if ( my @keys = keys %$sessions ) { + if ( + my @keys = + grep { $sessions->{$_}->{_session_kind} eq $self->sessionKind } + keys %$sessions + ) + { my $nb_sessions = $#keys + 1; @@ -1852,7 +1864,7 @@ sub createArtifactResponse { return; } - my $lassoSession = $session->data->{_lassoSessionDump}; + my $lassoSession = $session->data->{ $self->lsDump }; if ($lassoSession) { unless ( $self->setSessionFromDump( $login, $lassoSession ) ) { @@ -1880,7 +1892,7 @@ sub createArtifactResponse { if ( $session_id and $login->is_session_dirty ) { $self->logger->debug("Save Lasso session in session"); $self->updateSession( $req, - { _lassoSessionDump => $login->get_session->dump }, $session_id ); + { $self->lsDump => $login->get_session->dump }, $session_id ); } # Return artifact message @@ -2574,14 +2586,12 @@ sub sendLogoutRequestToProvider { "Build SOAP relay logout request for $providerID"); my $infos; - $infos->{type} = 'relay'; - $infos->{_utime} = time; - $infos->{_lassoSessionDump} = - $req->sessionInfo->{_lassoSessionDump}; - $infos->{_lassoIdentityDump} = - $req->sessionInfo->{_lassoIdentityDump}; - $infos->{_providerID} = $providerID; - $infos->{_relayState} = $logout->msg_relayState; + $infos->{type} = 'relay'; + $infos->{_utime} = time; + $infos->{ $self->lsDump } = $req->sessionInfo->{ $self->lsDump }; + $infos->{ $self->liDump } = $req->sessionInfo->{ $self->liDump }; + $infos->{_providerID} = $providerID; + $infos->{_relayState} = $logout->msg_relayState; # Create a new relay session my $relayInfos = $self->getSamlSession( undef, $infos ); @@ -2805,7 +2815,7 @@ sub getSamlSession { cacheModule => $self->conf->{localSessionStorage}, cacheModuleOptions => $self->conf->{localSessionStorageOptions}, id => $id, - kind => "SAML", + kind => $self->sessionKind, ( $info ? ( info => $info ) : () ), } ); @@ -2944,7 +2954,12 @@ sub deleteSAMLSecondarySessions { Lemonldap::NG::Common::Apache::Session->searchOn( $self->amOpts, "_saml_id", $session_id ); - if ( my @saml_sessions_keys = keys %$saml_sessions ) { + if ( + my @saml_sessions_keys = + grep { $saml_sessions->{$_}->{_session_kind} eq $self->sessionKind } + keys %$saml_sessions + ) + { foreach my $saml_session (@saml_sessions_keys) { diff --git a/lemonldap-ng-portal/t/30-SAML-Head-to-Tail-POST.t b/lemonldap-ng-portal/t/30-SAML-Head-to-Tail-POST.t index acf03991b..eb2c3d67c 100644 --- a/lemonldap-ng-portal/t/30-SAML-Head-to-Tail-POST.t +++ b/lemonldap-ng-portal/t/30-SAML-Head-to-Tail-POST.t @@ -10,7 +10,7 @@ BEGIN { require 't/saml-lib.pm'; } -my $maintests = 20; +my $maintests = 18; my $debug = 'error'; my ( $issuer, $sp, $res ); my %handlerOR = ( issuer => [], sp => [] ); @@ -125,14 +125,16 @@ SKIP: { ); # Verify authentication on SP - ($url,$s) = expectRedirection( $res, qr#^http://auth.sp.com(/?[^\?]*)(?:\?(.*))?$# ); + ( $url, $s ) = + expectRedirection( $res, qr#^http://auth.sp.com(/?[^\?]*)(?:\?(.*))?$# ); my $spId = expectCookie($res); ok( $res = $sp->_get( $url || '/', query => $s, - cookie => "lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId", + cookie => + "lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId", accept => 'text/html', ), ' Follow redirection' @@ -149,11 +151,12 @@ SKIP: { ), 'Query SP for logout' ); - #( $host, $url, $s ) = - # expectAutoPost( $res, 'auth.idp.com', '/saml/singleLogout', - # 'SAMLRequest' ); + ( $host, $url, $s ) = + expectAutoPost( $res, 'auth.idp.com', '/saml/singleLogout', + 'SAMLRequest' ); + #print STDERR Dumper($res); - skip 'todo', 8; + #skip 'todo', 8; # Push SAML logout request to IdP switch ('issuer'); @@ -182,7 +185,20 @@ SKIP: { ), 'Post SAML response to SP' ); - expectRedirection( $res, 'http://auth.sp.com' ); + ( $url, $s ) = + expectRedirection( $res, qr#^http://auth.sp.com(/.*?)(?:\?(.*))?$# ); + + # Follow redirection + ok( + $res = $sp->_get( + $url, + query => $s, + accept => 'text/html', + cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata', + ), + ' Follow redirection' + ); + diag "TODO: there is a loop here: http://auth.sp.com$url?$s"; # Test if logout is done switch ('issuer');