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 e3ca2b8fc..7991c3f71 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/SAML.pm @@ -84,7 +84,8 @@ sub extractFormInfo { # Check SAML Message my ( $request, $response, $method, $relaystate, $artifact ) = - $self->checkMessage( $url, $request_method, $content_type, "login" ); + $self->checkMessage( $req, $url, $request_method, $content_type, + "login" ); # Create Login object my $login = $self->createLogin( $self->lassoServer ); @@ -392,7 +393,8 @@ sub extractFormInfo { # Check SAML Message my ( $request, $response, $method, $relaystate, $artifact ) = - $self->checkMessage( $url, $request_method, $content_type, "logout" ); + $self->checkMessage( $req, $url, $request_method, $content_type, + "logout" ); # Create Logout object my $logout = $self->createLogout( $self->lassoServer ); 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 95ffb9b11..6a42ed6ba 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Issuer/SAML.pm @@ -47,7 +47,7 @@ sub init { my $saml_sso_art_url_ret = $self->getMetaDataURL( "samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact", 2 ); $self->ssoUrlRe( -qr/^\Q($saml_sso_soap_url|$saml_sso_soap_url_ret|$saml_sso_get_url|$saml_sso_get_url_ret|$saml_sso_post_url|$saml_sso_post_url_ret|$saml_sso_art_url|$saml_sso_art_url_ret)\E$/i +qr/^($saml_sso_soap_url|$saml_sso_soap_url_ret|$saml_sso_get_url|$saml_sso_get_url_ret|$saml_sso_post_url|$saml_sso_post_url_ret|$saml_sso_art_url|$saml_sso_art_url_ret)$/i ); my $saml_slo_soap_url = @@ -65,7 +65,7 @@ qr/^\Q($saml_sso_soap_url|$saml_sso_soap_url_ret|$saml_sso_get_url|$saml_sso_get $self->getMetaDataURL( "samlIDPSSODescriptorSingleLogoutServiceHTTPPost", 2 ); $self->sloRe( -qr/^(\Q$saml_slo_soap_url\E|\Q$saml_slo_soap_url_ret\E|\Q$saml_slo_get_url\E|\Q$saml_slo_get_url_ret\E|\Q$saml_slo_post_url\E|\Q$saml_slo_post_url_ret\E)$/i +qr/^($saml_slo_soap_url|$saml_slo_soap_url_ret|$saml_slo_get_url|$saml_slo_get_url_ret|$saml_slo_post_url|$saml_slo_post_url_ret)$/i ); return ( @@ -101,12 +101,12 @@ sub run { # Get HTTP request informations to know # if we are receving SAML request or response - my $url = $self->url( -absolute => 1 ); - my $request_method = $self->request_method(); - my $content_type = $self->content_type(); - my $idp_initiated = $self->param('IDPInitiated'); - my $idp_initiated_sp = $self->param('sp'); - my $idp_initiated_spConfKey = $self->param('spConfKey'); + my $url = $req->uri; + my $request_method = $req->method(); + my $content_type = $req->contentType(); + my $idp_initiated = $req->param('IDPInitiated'); + my $idp_initiated_sp = $req->param('sp'); + my $idp_initiated_spConfKey = $req->param('spConfKey'); # 1.1. SSO (SSO URL or Proxy Mode) if ( $url =~ $self->ssoUrlRe or $req->datas->{_proxiedRequest} ) { @@ -114,11 +114,12 @@ sub run { $self->lmLog( "URL $url detected as an SSO request URL", 'debug' ); # Get hidden params for IDP initiated if needed - $idp_initiated = $self->getHiddenFormValue('IDPInitiated') + $idp_initiated = $self->p->getHiddenFormValue( $req, 'IDPInitiated' ) unless defined $idp_initiated; - $idp_initiated_sp = $self->getHiddenFormValue('sp') + $idp_initiated_sp = $self->p->getHiddenFormValue( $req, 'sp' ) unless defined $idp_initiated_sp; - $idp_initiated_spConfKey = $self->getHiddenFormValue('spConfKey') + $idp_initiated_spConfKey = + $self->p->getHiddenFormValue( $req, 'spConfKey' ) unless defined $idp_initiated_spConfKey; # Check message @@ -132,7 +133,7 @@ sub run { } else { ( $request, $response, $method, $relaystate, $artifact ) = - $self->checkMessage( $url, $request_method, $content_type ); + $self->checkMessage( $req, $url, $request_method, $content_type ); } # Create Login object @@ -444,7 +445,7 @@ sub run { # Build Assertion unless ( $self->buildAssertion( - $login, $authn_context, $notOnOrAfterTimeout + $req, $login, $authn_context, $notOnOrAfterTimeout ) ) { @@ -501,7 +502,7 @@ sub run { my $nameIDContent; if ( defined $req->{sessionInfo}->{$nameIDSessionKey} ) { $nameIDContent = - $self->getFirstValue( + $self->p->getFirstValue( $req->{sessionInfo}->{$nameIDSessionKey} ); } @@ -730,7 +731,7 @@ sub run { last; } } - $self->_sub( 'userNotice', + $self->p->userNotice( "SAML authentication response sent to SAML SP $spConfKey for $user$nameIDLog" ); @@ -795,7 +796,7 @@ sub run { if ( $login->is_session_dirty ) { $self->lmLog( "Save Lasso session in session", 'debug' ); - $self->updateSession( + $self->p->updateSession( { _lassoSessionDump => $login->get_session->dump }, $session_id ); } @@ -903,7 +904,8 @@ sub run { $req->{postFields}->{'RelayState'} = $relaystate if ($relaystate); - return $self->_subProcess(qw(autoPost)); + $req->steps( ['autoPost'] ); + return PE_OK; } } @@ -931,7 +933,8 @@ sub run { # Check SAML Message my ( $request, $response, $method, $relaystate, $artifact ) = - $self->checkMessage( $url, $request_method, $content_type, "logout" ); + $self->checkMessage( $req, $url, $request_method, $content_type, + "logout" ); # Create Logout object my $logout = $self->createLogout($server); diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Issuer.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Issuer.pm index ebb586bfc..bcd773623 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Issuer.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Issuer.pm @@ -49,6 +49,10 @@ sub init { sub _redirect { my ( $self, $req ) = @_; + my $prms = $req->params; + foreach my $k ( keys %$prms ) { + $self->p->setHiddenFormValue( $req, $k, $prms->{$k}, '', 0 ); + } $req->{urldc} = $self->conf->{portal} . $req->path @@ -74,9 +78,6 @@ sub _redirect { sub _pRedirect { my ( $self, $req ) = @_; $req->parseBody; - - # TODO - die("TODO: store datas"); return $self->_redirect($req); } 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 d6d7290b5..887c9f124 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm @@ -518,7 +518,7 @@ sub setHiddenFormValue { # Store value if ($val) { $key = $prefix . $key; - $val = encode_base64($val) if $base64; + $val = encode_base64($val,'') if $base64; $req->{portalHiddenFormValues}->{$key} = $val; $self->lmLog( "Store $val in hidden key $key", 'debug' ); } @@ -572,4 +572,13 @@ sub clearHiddenFormValue { return; } +# Get the first value of a multivaluated session value +sub getFirstValue { + my ( $self, $value ) = @_; + + my @values = split /$self->{conf}->{multiValuesSeparator}/, $value; + + return $values[0]; +} + 1; diff --git a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML.t b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML.t index f859595a0..d1b62f71c 100644 --- a/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML.t +++ b/lemonldap-ng-portal/t/30-Auth-and-issuer-SAML.t @@ -4,7 +4,7 @@ use IO::String; require 't/test-lib.pm'; -my $maintests = 10; +my $maintests = 14; my $debug = 'debug'; my $res; my %handlerOR = ( issuer => [], sp => [] ); @@ -60,9 +60,9 @@ SKIP: { $res = $sp->_post( '/', IO::String->new( - "confirm=$confirm&idp=https://auth.idp.com/saml/metadata"), + "confirm=$confirm&idp=http://auth.idp.com/saml/metadata"), accept => 'text/html', - length => length($confirm) + 47, + length => length($confirm) + 46, ), 'Select IDP' ); @@ -72,13 +72,13 @@ SKIP: { ( defined( $cookies->{lemonldapidp} ) and $cookies->{lemonldapidp} eq - 'https://auth.idp.com/saml/metadata' + 'http://auth.idp.com/saml/metadata' ), 'IDP cookie defined' ) or explain( $res->[1], -'Set-Cookie => lemonldapidp=https://auth.idp.com/saml/metadata; domain=.sp.com; path=/' +'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp.com; path=/' ); ok( $res->[2]->[0] =~ @@ -90,6 +90,42 @@ SKIP: { ' _post( + $url, + IO::String->new($s), + accept => 'text/html', + length => length($s) + ), + 'Post SAML request to IdP' + ); + ok( $res->[0] == 200, 'Return code is 200' ); + my $body = $res->[2]->[0]; + $body =~ s/^.*?//s; + $body =~ s#.*$##s; + my %fields = + ( $body =~ / "IDP", - samlOrganizationURL => "https://www.idp.com/", + samlOrganizationURL => "http://www.idp.com/", samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAnfKBDG/K0TnGT7Xu8q1N45sNWvIK91SqNg8nvN2uVeKoHADT csus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9ryfSNDhWDWloNkpGEeWif2BnHUu46 @@ -357,6 +393,7 @@ sub sp { ini => { logLevel => $debug, domain => 'sp.com', + portal => 'http://auth.sp.com', authentication => 'SAML', userDB => 'SAML', issuerDBSAMLActivation => 0, @@ -379,7 +416,7 @@ sub sp { +entityID=\"http://auth.idp.com/saml/metadata\"> @@ -412,20 +449,20 @@ g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQ== - - - - + + + + urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos urn:oasis:names:tc:SAML:2.0:nameid-format:entity urn:oasis:names:tc:SAML:2.0:nameid-format:transient - - - - + + + + @@ -459,18 +496,18 @@ g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQ== - - - - + + + + urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos urn:oasis:names:tc:SAML:2.0:nameid-format:entity urn:oasis:names:tc:SAML:2.0:nameid-format:transient - - + + @@ -504,7 +541,7 @@ g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQ== - + urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName @@ -516,7 +553,7 @@ g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQ== IDP IDP -https://www.idp.fr/ +http://www.idp.fr/