diff --git a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Redirect-MultipleSP.t b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Redirect-MultipleSP.t new file mode 100644 index 000000000..444f9a109 --- /dev/null +++ b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML-Redirect-MultipleSP.t @@ -0,0 +1,712 @@ +use lib 'inc'; +use Test::More; +use strict; +use IO::String; +use LWP::UserAgent; +use LWP::Protocol::PSGI; +use MIME::Base64; + +BEGIN { + require 't/test-lib.pm'; + require 't/saml-lib.pm'; +} + +my $maintests = 27; +my $debug = 'error'; +my ( $issuer, $sp, $sp2, $res ); +my %handlerOR = ( issuer => [], sp => [], sp2 => [] ); + +# Redefine LWP methods for tests +LWP::Protocol::PSGI->register( + sub { + my $req = Plack::Request->new(@_); + fail('POST should not launch SOAP requests'); + count(1); + return [ 500, [], [] ]; + } +); + +SKIP: { + eval "use Lasso"; + if ($@) { + skip 'Lasso not found', $maintests; + } + + # Initialization + ok( $issuer = issuer(), 'Issuer portal' ); + $handlerOR{issuer} = \@Lemonldap::NG::Handler::Main::_onReload; + switch ('sp'); + &Lemonldap::NG::Handler::Main::cfgNum( 0, 0 ); + + ok( $sp = sp(), 'SP portal' ); + $handlerOR{sp} = \@Lemonldap::NG::Handler::Main::_onReload; + + ok( $sp2 = sp2(), 'SP2 portal' ); + $handlerOR{sp2} = \@Lemonldap::NG::Handler::Main::_onReload; + + # Simple SP access + my $res; + ok( + $res = $sp->_get( + '/', + accept => 'text/html', + query => 'url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw==' + ), + 'Unauth SP request' + ); + my ( $host, $url, $query ); + ok( + expectCookie( $res, 'lemonldapidp' ) eq + 'http://auth.idp.com/saml/metadata', + 'IDP cookie defined' + ) + or explain( + $res->[1], +'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp.com; path=/' + ); + ( $url, $query ) = expectRedirection( $res, + qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# ); + + # Push SAML request to IdP + switch ('issuer'); + ok( + $res = $issuer->_get( + $url, + query => $query, + accept => 'text/html', + ), + 'Launch SAML request to IdP' + ); + expectOK($res); + my $pdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' ); + + # Try to authenticate to IdP + my $body = $res->[2]->[0]; + $body =~ s/^.*?//s; + $body =~ s#.*$##s; + my %fields = + ( $body =~ /_get("/sessions/global/$spId"), 'Get UTF-8' ); + expectOK($res); + ok( $res = eval { JSON::from_json( $res->[2]->[0] ) }, ' GET JSON' ) + or print STDERR $@; + ok( $res->{cn} eq 'Frédéric Accents', 'UTF-8 values' ) + or explain( $res, 'cn => Frédéric Accents' ); + + # Simple SP2 access + + switch ('sp2'); + ok( + $res = $sp2->_get( + '/', + accept => 'text/html', + query => 'url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw==' + ), + 'Unauth SP2 request' + ); + + ok( + expectCookie( $res, 'lemonldapidp' ) eq + 'http://auth.idp.com/saml/metadata', + 'IDP cookie defined' + ) + or explain( + $res->[1], +'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp2.com; path=/' + ); + ( $url, $query ) = expectRedirection( $res, + qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# ); + + # Push SAML request to IdP + switch ('issuer'); + ok( + $res = $issuer->_get( + $url, + query => $query, + accept => 'text/html', + cookie => "lemonldap=$idpId", + ), + 'Launch SAML request to IdP' + ); + ( $host, $url, $query ) = + expectForm( $res, 'auth.sp2.com', '/saml/proxySingleSignOnPost', + 'SAMLResponse', 'RelayState' ); + + # Post SAML response to SP2 + switch ('sp2'); + ok( + $res = $sp2->_post( + $url, IO::String->new($query), + accept => 'text/html', + length => length($query), + cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata', + ), + 'Post SAML response to SP2' + ); + my $sp2Id = expectCookie($res); + expectRedirection( $res, 'http://test1.example.com/' ); + + ok( $res = $sp2->_get( '/', cookie => "lemonldap=$spId" ), 'Get / on SP2' ); + expectOK($res); + expectAuthenticatedAs( $res, 'fa@badwolf.org@idp' ); + + # Logout initiated by SP + ok( + $res = $sp->_get( + '/', + query => 'logout', + cookie => "lemonldap=$spId", + accept => 'text/html' + ), + 'Query SP for logout' + ); + + ( $url, $query ) = expectRedirection( $res, + qr#^http://auth.idp.com(/saml/singleLogout)\?(SAMLRequest=.+)# ); + + # Push SAML logout request to IdP + switch ('issuer'); + ok( + $res = $issuer->_get( + $url, + query => $query, + accept => 'text/html', + cookie => "lemonldap=$idpId", + ), + 'Launch SAML logout request to IdP' + ); + + my $relaypage = $res; + + ok( $res->[2]->[0] =~ + m%