Merge branch 'v2.0'
This commit is contained in:
commit
8941ee4dd5
|
@ -29,6 +29,7 @@ sub defaultValues {
|
|||
'casAuthnLevel' => 1,
|
||||
'checkTime' => 600,
|
||||
'checkUserHiddenAttributes' => '_2fDevices _loginHistory hGroups',
|
||||
'checkUserIdRule' => 1,
|
||||
'checkXSS' => 1,
|
||||
'confirmFormMethod' => 'post',
|
||||
'cookieName' => 'lemonldap',
|
||||
|
@ -71,6 +72,7 @@ sub defaultValues {
|
|||
'httpOnly' => 1,
|
||||
'https' => -1,
|
||||
'impersonationHiddenAttributes' => '_2fDevices _loginHistory',
|
||||
'impersonationIdRule' => 1,
|
||||
'impersonationPrefix' => 'real_',
|
||||
'impersonationRule' => 0,
|
||||
'impersonationSkipEmptyValues' => 1,
|
||||
|
@ -245,6 +247,7 @@ sub defaultValues {
|
|||
'samlOrganizationDisplayName' => 'Example',
|
||||
'samlOrganizationName' => 'Example',
|
||||
'samlOrganizationURL' => 'http://www.example.com',
|
||||
'samlOverrideIDPEntityID' => '',
|
||||
'samlRelayStateTimeout' => 600,
|
||||
'samlServiceSignatureMethod' => 'RSA_SHA1',
|
||||
'samlSPSSODescriptorArtifactResolutionServiceArtifact' =>
|
||||
|
|
|
@ -66,7 +66,7 @@ our $issuerParameters = {
|
|||
issuerDBOpenIDConnect => [qw(issuerDBOpenIDConnectActivation issuerDBOpenIDConnectPath issuerDBOpenIDConnectRule)],
|
||||
issuerDBSAML => [qw(issuerDBSAMLActivation issuerDBSAMLPath issuerDBSAMLRule)],
|
||||
};
|
||||
our $samlServiceParameters = [qw(samlEntityID samlServicePrivateKeySig samlServicePrivateKeySigPwd samlServicePublicKeySig samlServicePrivateKeyEnc samlServicePrivateKeyEncPwd samlServicePublicKeyEnc samlServiceUseCertificateInResponse samlServiceSignatureMethod samlNameIDFormatMapEmail samlNameIDFormatMapX509 samlNameIDFormatMapWindows samlNameIDFormatMapKerberos samlAuthnContextMapPassword samlAuthnContextMapPasswordProtectedTransport samlAuthnContextMapTLSClient samlAuthnContextMapKerberos samlOrganizationDisplayName samlOrganizationName samlOrganizationURL samlSPSSODescriptorAuthnRequestsSigned samlSPSSODescriptorWantAssertionsSigned samlSPSSODescriptorSingleLogoutServiceHTTPRedirect samlSPSSODescriptorSingleLogoutServiceHTTPPost samlSPSSODescriptorSingleLogoutServiceSOAP samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact samlSPSSODescriptorAssertionConsumerServiceHTTPPost samlSPSSODescriptorArtifactResolutionServiceArtifact samlIDPSSODescriptorWantAuthnRequestsSigned samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect samlIDPSSODescriptorSingleSignOnServiceHTTPPost samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect samlIDPSSODescriptorSingleLogoutServiceHTTPPost samlIDPSSODescriptorSingleLogoutServiceSOAP samlIDPSSODescriptorArtifactResolutionServiceArtifact samlAttributeAuthorityDescriptorAttributeServiceSOAP samlIdPResolveCookie samlMetadataForceUTF8 samlStorage samlStorageOptions samlRelayStateTimeout samlUseQueryStringSpecific samlCommonDomainCookieActivation samlCommonDomainCookieDomain samlCommonDomainCookieReader samlCommonDomainCookieWriter samlDiscoveryProtocolActivation samlDiscoveryProtocolURL samlDiscoveryProtocolPolicy samlDiscoveryProtocolIsPassive)];
|
||||
our $samlServiceParameters = [qw(samlEntityID samlServicePrivateKeySig samlServicePrivateKeySigPwd samlServicePublicKeySig samlServicePrivateKeyEnc samlServicePrivateKeyEncPwd samlServicePublicKeyEnc samlServiceUseCertificateInResponse samlServiceSignatureMethod samlNameIDFormatMapEmail samlNameIDFormatMapX509 samlNameIDFormatMapWindows samlNameIDFormatMapKerberos samlAuthnContextMapPassword samlAuthnContextMapPasswordProtectedTransport samlAuthnContextMapTLSClient samlAuthnContextMapKerberos samlOrganizationDisplayName samlOrganizationName samlOrganizationURL samlSPSSODescriptorAuthnRequestsSigned samlSPSSODescriptorWantAssertionsSigned samlSPSSODescriptorSingleLogoutServiceHTTPRedirect samlSPSSODescriptorSingleLogoutServiceHTTPPost samlSPSSODescriptorSingleLogoutServiceSOAP samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact samlSPSSODescriptorAssertionConsumerServiceHTTPPost samlSPSSODescriptorArtifactResolutionServiceArtifact samlIDPSSODescriptorWantAuthnRequestsSigned samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect samlIDPSSODescriptorSingleSignOnServiceHTTPPost samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect samlIDPSSODescriptorSingleLogoutServiceHTTPPost samlIDPSSODescriptorSingleLogoutServiceSOAP samlIDPSSODescriptorArtifactResolutionServiceArtifact samlAttributeAuthorityDescriptorAttributeServiceSOAP samlIdPResolveCookie samlMetadataForceUTF8 samlStorage samlStorageOptions samlRelayStateTimeout samlUseQueryStringSpecific samlCommonDomainCookieActivation samlCommonDomainCookieDomain samlCommonDomainCookieReader samlCommonDomainCookieWriter samlDiscoveryProtocolActivation samlDiscoveryProtocolURL samlDiscoveryProtocolPolicy samlDiscoveryProtocolIsPassive samlOverrideIDPEntityID)];
|
||||
our $oidcServiceParameters = [qw(oidcServiceMetaDataIssuer oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI oidcServiceMetaDataEndSessionURI oidcServiceMetaDataCheckSessionURI oidcServiceMetaDataFrontChannelURI oidcServiceMetaDataBackChannelURI oidcServiceMetaDataAuthnContext oidcServicePrivateKeySig oidcServicePublicKeySig oidcServiceKeyIdSig oidcServiceAllowDynamicRegistration oidcServiceAllowAuthorizationCodeFlow oidcServiceAllowImplicitFlow oidcServiceAllowHybridFlow oidcStorage oidcStorageOptions)];
|
||||
|
||||
1;
|
||||
|
|
|
@ -53,6 +53,11 @@ sub serviceToXML {
|
|||
$template->param( $_, $self->getValue( $_, $conf ) );
|
||||
}
|
||||
|
||||
# When asked to provide only IDP metadata, take into account EntityID override
|
||||
if ( $type eq "idp" and $conf->{samlOverrideIDPEntityID} ) {
|
||||
$template->param( 'samlEntityID', $conf->{samlOverrideIDPEntityID} );
|
||||
}
|
||||
|
||||
# Boolean parameters
|
||||
my @param_boolean = qw(
|
||||
samlSPSSODescriptorAuthnRequestsSigned
|
||||
|
|
|
@ -783,6 +783,21 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'default' => '_2fDevices _loginHistory hGroups',
|
||||
'type' => 'text'
|
||||
},
|
||||
'checkUserIdRule' => {
|
||||
'default' => 1,
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
'Safe'->new->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
},
|
||||
'type' => 'text'
|
||||
},
|
||||
'checkXSS' => {
|
||||
'default' => 1,
|
||||
'type' => 'bool'
|
||||
|
@ -1199,6 +1214,21 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
'default' => '_2fDevices _loginHistory',
|
||||
'type' => 'text'
|
||||
},
|
||||
'impersonationIdRule' => {
|
||||
'default' => 1,
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
'Safe'->new->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
},
|
||||
'type' => 'text'
|
||||
},
|
||||
'impersonationMergeSSOgroups' => {
|
||||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
|
@ -2885,6 +2915,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'default' => 'http://www.example.com',
|
||||
'type' => 'text'
|
||||
},
|
||||
'samlOverrideIDPEntityID' => {
|
||||
'default' => '',
|
||||
'type' => 'text'
|
||||
},
|
||||
'samlRelayStateTimeout' => {
|
||||
'default' => 600,
|
||||
'type' => 'int'
|
||||
|
|
|
@ -422,6 +422,12 @@ sub attributes {
|
|||
documentation => 'Enable check user',
|
||||
flags => 'p',
|
||||
},
|
||||
checkUserIdRule => {
|
||||
type => 'text',
|
||||
test => $perlExpr,
|
||||
default => 1,
|
||||
documentation => 'checkUser identities rule',
|
||||
},
|
||||
checkUserHiddenAttributes => {
|
||||
type => 'text',
|
||||
default => '_2fDevices _loginHistory hGroups',
|
||||
|
@ -457,6 +463,12 @@ sub attributes {
|
|||
default => 0,
|
||||
documentation => 'Impersonation activation rule',
|
||||
},
|
||||
impersonationIdRule => {
|
||||
type => 'text',
|
||||
test => $perlExpr,
|
||||
default => 1,
|
||||
documentation => 'Impersonation identities rule',
|
||||
},
|
||||
impersonationHiddenAttributes => {
|
||||
type => 'text',
|
||||
default => '_2fDevices _loginHistory',
|
||||
|
@ -2021,6 +2033,11 @@ sub attributes {
|
|||
default => 600,
|
||||
documentation => 'SAML timeout of relay state',
|
||||
},
|
||||
samlOverrideIDPEntityID => {
|
||||
type => 'text',
|
||||
documentation => 'Override SAML EntityID when acting as an IDP',
|
||||
default => '',
|
||||
},
|
||||
samlUseQueryStringSpecific => {
|
||||
default => 0,
|
||||
type => 'bool',
|
||||
|
|
|
@ -642,6 +642,7 @@ sub tree {
|
|||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'checkUser',
|
||||
'checkUserIdRule',
|
||||
'checkUserHiddenAttributes',
|
||||
'checkUserDisplayPersistentInfo',
|
||||
'checkUserDisplayEmptyValues',
|
||||
|
@ -653,6 +654,7 @@ sub tree {
|
|||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'impersonationRule',
|
||||
'impersonationIdRule',
|
||||
'impersonationPrefix',
|
||||
'impersonationHiddenAttributes',
|
||||
'impersonationSkipEmptyValues',
|
||||
|
@ -1008,7 +1010,8 @@ sub tree {
|
|||
'samlDiscoveryProtocolPolicy',
|
||||
'samlDiscoveryProtocolIsPassive'
|
||||
]
|
||||
}
|
||||
},
|
||||
'samlOverrideIDPEntityID',
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
"checkStateSecret":"Shared secret",
|
||||
"checkUsers":"SSO profile Check",
|
||||
"checkUser":"Activation",
|
||||
"checkUserIdRule":"Identities use rule",
|
||||
"checkUserHiddenAttributes":"Hidden attributes",
|
||||
"checkUserDisplayPersistentInfo":"Display persistent session",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
|
@ -288,6 +289,7 @@
|
|||
"https":"إتش تي تي بي س",
|
||||
"impersonation":"Impersonation",
|
||||
"impersonationRule":"Use rule",
|
||||
"impersonationIdRule":"Identities use rule",
|
||||
"impersonationHiddenAttributes":"Hidden attributes",
|
||||
"impersonationMergeSSOgroups":"Merge spoofed and real SSO groups",
|
||||
"impersonationPrefix":"Real attributes prefix",
|
||||
|
@ -975,5 +977,6 @@
|
|||
"samlCommonDomainCookieReader":"يو آر إل القارئ",
|
||||
"samlCommonDomainCookieWriter":"يو آر إل الكاتب",
|
||||
"samlRelayStateTimeout":"تناوب حالة مهلة الجلسة ",
|
||||
"samlUseQueryStringSpecific":"استخدام أسلوب query_string المعين"
|
||||
}
|
||||
"samlUseQueryStringSpecific":"استخدام أسلوب query_string المعين",
|
||||
"samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
|
||||
}
|
||||
|
|
|
@ -152,11 +152,12 @@
|
|||
"checkState":"Activation",
|
||||
"checkStateSecret":"Shared secret",
|
||||
"checkUsers":"SSO profile Check",
|
||||
"choiceParams":"Choice parameters",
|
||||
"checkUser":"Activation",
|
||||
"checkUserIdRule":"Identities use rule",
|
||||
"checkUserHiddenAttributes":"Hidden attributes",
|
||||
"checkUserDisplayPersistentInfo":"Display persistent session",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
"choiceParams":"Choice parameters",
|
||||
"chooseLogo":"Choose logo",
|
||||
"chooseSkin":"Choose skin",
|
||||
"combination":"Combination",
|
||||
|
@ -288,6 +289,7 @@
|
|||
"https":"HTTPS",
|
||||
"impersonation":"Impersonation",
|
||||
"impersonationRule":"Use rule",
|
||||
"impersonationIdRule":"Identities use rule",
|
||||
"impersonationHiddenAttributes":"Hidden attributes",
|
||||
"impersonationMergeSSOgroups":"Merge spoofed and real SSO groups",
|
||||
"impersonationPrefix":"Real attributes prefix",
|
||||
|
@ -975,5 +977,6 @@
|
|||
"samlCommonDomainCookieReader":"Reader URL",
|
||||
"samlCommonDomainCookieWriter":"Writer URL",
|
||||
"samlRelayStateTimeout":"RelayState session timeout",
|
||||
"samlUseQueryStringSpecific":"Use specific query_string method"
|
||||
}
|
||||
"samlUseQueryStringSpecific":"Use specific query_string method",
|
||||
"samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
"checkStateSecret":"Shared secret",
|
||||
"checkUsers":"SSO profile Check",
|
||||
"checkUser":"Activation",
|
||||
"checkUserIdRule":"Identities use rule",
|
||||
"checkUserHiddenAttributes":"Hidden attributes",
|
||||
"checkUserDisplayPersistentInfo":"Display persistent session",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
|
@ -288,6 +289,7 @@
|
|||
"https":"HTTPS",
|
||||
"impersonation":"Impersonation",
|
||||
"impersonationRule":"Use rule",
|
||||
"impersonationIdRule":"Identities use rule",
|
||||
"impersonationHiddenAttributes":"Hidden attributes",
|
||||
"impersonationMergeSSOgroups":"Merge spoofed and real SSO groups",
|
||||
"impersonationPrefix":"Real attributes prefix",
|
||||
|
@ -975,5 +977,6 @@
|
|||
"samlCommonDomainCookieReader":"Reader URL",
|
||||
"samlCommonDomainCookieWriter":"Writer URL",
|
||||
"samlRelayStateTimeout":"RelayState session timeout",
|
||||
"samlUseQueryStringSpecific":"Use specific query_string method"
|
||||
"samlUseQueryStringSpecific":"Use specific query_string method",
|
||||
"samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
"checkStateSecret":"Secret partagé",
|
||||
"checkUsers":"Vérification des profils SSO",
|
||||
"checkUser":"Activation",
|
||||
"checkUserIdRule":"Règle d'utilisation des identités",
|
||||
"checkUserHiddenAttributes":"Attributs masqués",
|
||||
"checkUserDisplayPersistentInfo":"Afficher les données de session persistante",
|
||||
"checkUserDisplayEmptyValues":"Afficher les valeurs nulles",
|
||||
|
@ -288,6 +289,7 @@
|
|||
"https":"HTTPS",
|
||||
"impersonation":"Usurpation d'identité",
|
||||
"impersonationRule":"Règle d'utilisation",
|
||||
"impersonationIdRule":"Règle d'utilisation des identités",
|
||||
"impersonationHiddenAttributes":"Attributs masqués",
|
||||
"impersonationMergeSSOgroups":"Fusionner les groupes SSO réels et usurpés",
|
||||
"impersonationPrefix":"Préfix des vrais attributs",
|
||||
|
@ -975,5 +977,6 @@
|
|||
"samlCommonDomainCookieReader":"URL de lecture",
|
||||
"samlCommonDomainCookieWriter":"URL d'écriture",
|
||||
"samlRelayStateTimeout":"Durée de vie d'une session RelayState",
|
||||
"samlUseQueryStringSpecific":"Utilisation d'une fonction spécifique pour query_string"
|
||||
"samlUseQueryStringSpecific":"Utilisation d'une fonction spécifique pour query_string",
|
||||
"samlOverrideIDPEntityID": "Valeur de l'Entity ID en mode IDP"
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
"checkStateSecret":"Segreto condiviso",
|
||||
"checkUsers":"SSO profile Check",
|
||||
"checkUser":"Activation",
|
||||
"checkUserIdRule":"Identities use rule",
|
||||
"checkUserHiddenAttributes":"Hidden attributes",
|
||||
"checkUserDisplayPersistentInfo":"Display persistent session",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
|
@ -288,6 +289,7 @@
|
|||
"https":"HTTPS",
|
||||
"impersonation":"Impersonation",
|
||||
"impersonationRule":"Use rule",
|
||||
"impersonationIdRule":"Identities use rule",
|
||||
"impersonationHiddenAttributes":"Hidden attributes",
|
||||
"impersonationMergeSSOgroups":"Merge spoofed and real SSO groups",
|
||||
"impersonationPrefix":"Real attributes prefix",
|
||||
|
@ -975,5 +977,6 @@
|
|||
"samlCommonDomainCookieReader":"URL del lettore",
|
||||
"samlCommonDomainCookieWriter":"URL dell'autore",
|
||||
"samlRelayStateTimeout":"Timeout di sessione di RelayState",
|
||||
"samlUseQueryStringSpecific":"Utilizza il metodo specifico query_string"
|
||||
}
|
||||
"samlUseQueryStringSpecific":"Utilizza il metodo specifico query_string",
|
||||
"samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
|
||||
}
|
||||
|
|
|
@ -151,8 +151,9 @@
|
|||
"clickHereToForce":"Nhấp vào đây để bắt buộc",
|
||||
"checkState":"Kích hoạt",
|
||||
"checkStateSecret":"Shared secret",
|
||||
"checkUsers":"Session Check",
|
||||
"checkUsers":"SSO profile Check",
|
||||
"checkUser":"Activation",
|
||||
"checkUserIdRule":"Identities use rule",
|
||||
"checkUserHiddenAttributes":"Hidden attributes",
|
||||
"checkUserDisplayPersistentInfo":"Display persistent session",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
|
@ -288,6 +289,7 @@
|
|||
"https":"HTTPS",
|
||||
"impersonation":"Impersonation",
|
||||
"impersonationRule":"Use rule",
|
||||
"impersonationIdRule":"Identities use rule",
|
||||
"impersonationHiddenAttributes":"Hidden attributes",
|
||||
"impersonationMergeSSOgroups":"Merge spoofed and real SSO groups",
|
||||
"impersonationPrefix":"Real attributes prefix",
|
||||
|
@ -975,5 +977,6 @@
|
|||
"samlCommonDomainCookieReader":"Trình đọc URL",
|
||||
"samlCommonDomainCookieWriter":"Trình viết URL",
|
||||
"samlRelayStateTimeout":"Thời gian hết hạn phiên RelayState ",
|
||||
"samlUseQueryStringSpecific":"Sử dụng phương pháp query_string cụ thể"
|
||||
}
|
||||
"samlUseQueryStringSpecific":"Sử dụng phương pháp query_string cụ thể",
|
||||
"samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
"checkStateSecret":"Shared secret",
|
||||
"checkUsers":"SSO profile Check",
|
||||
"checkUser":"Activation",
|
||||
"checkUserIdRule":"Identities use rule",
|
||||
"checkUserHiddenAttributes":"Hidden attributes",
|
||||
"checkUserDisplayPersistentInfo":"Display persistent session",
|
||||
"checkUserDisplayEmptyValues":"Display empty values",
|
||||
|
@ -288,6 +289,7 @@
|
|||
"https":"HTTPS",
|
||||
"impersonation":"Impersonation",
|
||||
"impersonationRule":"Use rule",
|
||||
"impersonationIdRule":"Identities use rule",
|
||||
"impersonationHiddenAttributes":"Hidden attributes",
|
||||
"impersonationMergeSSOgroups":"Merge spoofed and real SSO groups",
|
||||
"impersonationPrefix":"Real attributes prefix",
|
||||
|
@ -975,5 +977,6 @@
|
|||
"samlCommonDomainCookieReader":"Reader URL",
|
||||
"samlCommonDomainCookieWriter":"Writer URL",
|
||||
"samlRelayStateTimeout":"RelayState session timeout",
|
||||
"samlUseQueryStringSpecific":"Use specific query_string method"
|
||||
}
|
||||
"samlUseQueryStringSpecific":"Use specific query_string method",
|
||||
"samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -114,6 +114,7 @@ sub extractFormInfo {
|
|||
#$self->p->setHiddenFormValue( $req, kerberos => 0, '', 0 );
|
||||
eval( $self->InitCmd );
|
||||
die 'Unable to launch init commmand ' . $self->{InitCmd} if ($@);
|
||||
$req->data->{waitingMessage} = 1;
|
||||
return PE_FIRSTACCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -893,6 +893,10 @@ sub extractFormInfo {
|
|||
$self->logger->debug(
|
||||
"Will try to use SAML Discovery Protocol for IDP resolution");
|
||||
|
||||
if ($req->urldc) {
|
||||
$req->pdata->{_url} = encode_base64($req->urldc, '');
|
||||
}
|
||||
|
||||
my $disco_url = $self->conf->{samlDiscoveryProtocolURL};
|
||||
|
||||
my $portal = $self->conf->{portal};
|
||||
|
|
|
@ -51,6 +51,7 @@ sub extractFormInfo {
|
|||
$req->data->{customScript} .= $self->{AjaxInitScript};
|
||||
$self->logger->debug(
|
||||
"Send init/script -> " . $req->data->{customScript} );
|
||||
$req->data->{waitingMessage} = 1;
|
||||
return PE_FIRSTACCESS;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -91,6 +91,11 @@ qr/^($saml_sso_get_url|$saml_sso_get_url_ret|$saml_sso_post_url|$saml_sso_post_u
|
|||
);
|
||||
return 0 unless ($res);
|
||||
|
||||
if ( $self->conf->{samlOverrideIDPEntityID} ) {
|
||||
$self->lassoServer->ProviderID(
|
||||
$self->conf->{samlOverrideIDPEntityID} );
|
||||
}
|
||||
|
||||
# Single logout routes
|
||||
$self->addUnauthRouteFromMetaDataURL(
|
||||
"samlIDPSSODescriptorSingleLogoutServiceSOAP",
|
||||
|
@ -165,6 +170,8 @@ sub storeEnv {
|
|||
$self->checkMessage( $req, $req->uri, $req->method, $req->content_type );
|
||||
return PE_OK if ( $artifact or !$request );
|
||||
my $login = $self->createLogin( $self->lassoServer );
|
||||
$self->disableSignatureVerification($login);
|
||||
$self->processAuthnRequestMsg( $login, $request );
|
||||
if ( my $sp = $login->remote_providerID() ) {
|
||||
$req->env->{llng_saml_sp} = $sp;
|
||||
if ( my $spConfKey = $self->spList->{$sp}->{confKey} ) {
|
||||
|
@ -1924,7 +1931,16 @@ sub imgnok {
|
|||
|
||||
sub sendImage {
|
||||
my ( $self, $req,, $img ) = @_;
|
||||
return $self->p->staticFile( $req, "common/$img", 'image/png' );
|
||||
return [
|
||||
302,
|
||||
[
|
||||
'Location' => $self->conf->{portal}
|
||||
. $self->p->staticPrefix
|
||||
. '/common/'
|
||||
. $img,
|
||||
],
|
||||
[],
|
||||
];
|
||||
}
|
||||
|
||||
# Normalize url to be tolerant to SAML Path
|
||||
|
|
|
@ -186,7 +186,7 @@ sub loadService {
|
|||
|
||||
# Create Lasso server with service metadata
|
||||
my $server = $self->createServer(
|
||||
$service_metadata->serviceToXML( $self->conf ),
|
||||
$service_metadata->serviceToXML( $self->conf, ''),
|
||||
$self->conf->{samlServicePrivateKeySig},
|
||||
$self->conf->{samlServicePrivateKeySigPwd},
|
||||
|
||||
|
@ -2385,6 +2385,18 @@ sub samldate2timestamp {
|
|||
sub sendLogoutResponseToServiceProvider {
|
||||
my ( $self, $req, $logout, $method ) = @_;
|
||||
|
||||
my $httpmethod = $self->getFirstHttpMethod(
|
||||
$self->lassoServer,
|
||||
$logout->remote_providerID,
|
||||
Lasso::Constants::MD_PROTOCOL_TYPE_SINGLE_LOGOUT
|
||||
);
|
||||
if ( $httpmethod == Lasso::Constants::HTTP_METHOD_NONE ) {
|
||||
$self->logger->warn( "Provider "
|
||||
. $logout->remote_providerID
|
||||
. " has no SingleLogoutService in metadata, staying on portal" );
|
||||
return $self->p->do( $req, [] );
|
||||
}
|
||||
|
||||
# Logout response
|
||||
unless ( $self->buildLogoutResponseMsg($logout) ) {
|
||||
return $self->p->sendError( $req, "Unable to build SLO response", 500 );
|
||||
|
@ -3074,7 +3086,7 @@ sub importRealSession {
|
|||
|
||||
sub metadata {
|
||||
my ( $self, $req ) = @_;
|
||||
my $type = $req->param('type');
|
||||
my $type = $req->param('type') || 'all';
|
||||
require Lemonldap::NG::Common::Conf::SAML::Metadata;
|
||||
if ( my $metadata = Lemonldap::NG::Common::Conf::SAML::Metadata->new() ) {
|
||||
my $s = $metadata->serviceToXML( $self->conf, $type );
|
||||
|
|
|
@ -113,7 +113,7 @@ sub display {
|
|||
&& $req->data->{login},
|
||||
ASK_LOGINS => $req->param('checkLogins') || 0,
|
||||
CONFIRMKEY => $self->stamp(),
|
||||
LIST => $req->data->{list} || [],
|
||||
LIST => $req->data->{list} || [],
|
||||
REMEMBER => $req->data->{confirmRemember},
|
||||
(
|
||||
$req->data->{customScript}
|
||||
|
@ -420,6 +420,10 @@ sub display {
|
|||
|
||||
}
|
||||
|
||||
if ( $req->data->{waitingMessage} ) {
|
||||
$templateParams{WAITING_MESSAGE} = 1;
|
||||
}
|
||||
|
||||
$self->logger->debug("Skin returned: $skinfile");
|
||||
return ( $skinfile, \%templateParams );
|
||||
}
|
||||
|
|
|
@ -351,7 +351,7 @@ sub reloadConf {
|
|||
}
|
||||
};
|
||||
my $portal = $self->conf->{portal};
|
||||
$portal =~ s#^https?://(.*?)(?:/|$)/#$1#;
|
||||
$portal =~ s#^https?://(.*?)(?:[:/].*)?$#$1#;
|
||||
HANDLER->tsv->{defaultCondition}->{$portal} ||= sub { 1 };
|
||||
|
||||
1;
|
||||
|
|
|
@ -25,6 +25,7 @@ has ott => (
|
|||
return $ott;
|
||||
}
|
||||
);
|
||||
has idRule => ( is => 'rw', default => sub { 1 } );
|
||||
|
||||
sub hAttr {
|
||||
$_[0]->{conf}->{checkUserHiddenAttributes} . ' '
|
||||
|
@ -33,8 +34,22 @@ sub hAttr {
|
|||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
my $hd = $self->p->HANDLER;
|
||||
$self->addAuthRoute( checkuser => 'check', ['POST'] );
|
||||
$self->addAuthRoute( checkuser => 'display', ['GET'] );
|
||||
|
||||
# Parse identity rule
|
||||
$self->logger->debug(
|
||||
"checkUser identities rule -> " . $self->conf->{checkUserIdRule} );
|
||||
my $rule =
|
||||
$hd->buildSub( $hd->substitute( $self->conf->{checkUserIdRule} ) );
|
||||
unless ($rule) {
|
||||
$self->error(
|
||||
"Bad checkUser identities rule -> " . $hd->tsv->{jail}->error );
|
||||
return 0;
|
||||
}
|
||||
$self->{idRule} = $rule;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -49,12 +64,12 @@ sub check {
|
|||
if ( $self->conf->{requireToken} ) {
|
||||
my $token = $req->param('token');
|
||||
unless ($token) {
|
||||
$self->userLogger->warn('CheckUser try without token');
|
||||
$self->userLogger->warn('checkUser try without token');
|
||||
$msg = PE_NOTOKEN;
|
||||
$token = $self->ott->createToken( $req->userData );
|
||||
}
|
||||
unless ( $self->ott->getToken($token) ) {
|
||||
$self->userLogger->warn('Checkuser try with expired/bad token');
|
||||
$self->userLogger->warn('checkUser try with expired/bad token');
|
||||
$msg = PE_TOKENEXPIRED;
|
||||
$token = $self->ott->createToken( $req->userData );
|
||||
}
|
||||
|
@ -64,6 +79,7 @@ sub check {
|
|||
LANGS => $self->conf->{showLanguages},
|
||||
MSG => "PE$msg",
|
||||
ALERTE => 'alert-warning',
|
||||
LOGIN => '',
|
||||
TOKEN => $token,
|
||||
};
|
||||
return $self->p->sendJSONresponse( $req, $params )
|
||||
|
@ -91,7 +107,7 @@ sub check {
|
|||
LANGS => $self->conf->{showLanguages},
|
||||
MSG => 'PE' . PE_MALFORMEDUSER,
|
||||
ALERTE => 'alert-warning',
|
||||
LOGIN => $req->{user},
|
||||
LOGIN => '',
|
||||
TOKEN => (
|
||||
$self->conf->{requireToken}
|
||||
? $self->ott->createToken( $req->userData )
|
||||
|
@ -108,7 +124,7 @@ sub check {
|
|||
$attrs = $req->userData;
|
||||
}
|
||||
else {
|
||||
$self->logger->debug("Check requested for $req->{user}");
|
||||
$self->logger->debug("checkUser requested for $req->{user}");
|
||||
$req->{user} = $user;
|
||||
$self->userLogger->notice(
|
||||
"Retrieve session from userDB and compute Groups & Macros");
|
||||
|
@ -183,8 +199,8 @@ sub check {
|
|||
MSG => $msg,
|
||||
ALERTE => ( $msg eq 'checkUser' ? 'alert-info' : 'alert-warning' ),
|
||||
LOGIN => (
|
||||
$self->p->checkXSSAttack( 'LOGIN', $req->{user} ) ? ""
|
||||
: $req->{user}
|
||||
$self->p->checkXSSAttack( 'LOGIN', $req->{userData}->{uid} ) ? ""
|
||||
: $req->{userData}->{uid}
|
||||
),
|
||||
URL => (
|
||||
$self->p->checkXSSAttack( 'URL', $url ) ? ""
|
||||
|
@ -210,19 +226,47 @@ sub check {
|
|||
|
||||
sub display {
|
||||
my ( $self, $req ) = @_;
|
||||
my ( $attrs, $array_attrs ) = ( {}, [] );
|
||||
|
||||
$self->userLogger->notice("Retrieve session from Sessions database");
|
||||
$self->userLogger->warn("Using spoofed SSO groups if exist!!!")
|
||||
if ( $self->conf->{impersonationRule} );
|
||||
$attrs = $req->userData;
|
||||
|
||||
# Create an array of hashes for template loop
|
||||
$self->logger->debug("Delete hidden or empty attributes");
|
||||
if ( $self->conf->{checkUserDisplayEmptyValues} ) {
|
||||
foreach my $k ( sort keys %$attrs ) {
|
||||
|
||||
# Ignore hidden attributes
|
||||
push @$array_attrs, { key => $k, value => $attrs->{$k} }
|
||||
unless ( $self->hAttr =~ /\b$k\b/ );
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach my $k ( sort keys %$attrs ) {
|
||||
|
||||
# Ignore hidden attributes and empty values
|
||||
push @$array_attrs, { key => $k, value => $attrs->{$k} }
|
||||
unless ( $self->hAttr =~ /\b$k\b/ or !$attrs->{$k} );
|
||||
}
|
||||
}
|
||||
|
||||
# ARRAY_REF = [ A_REF GROUPS, A_REF MACROS, A_REF OTHERS ]
|
||||
$array_attrs = $self->_splitAttributes($array_attrs);
|
||||
|
||||
# Display form
|
||||
my $params = {
|
||||
PORTAL => $self->conf->{portal},
|
||||
MAIN_LOGO => $self->conf->{portalMainLogo},
|
||||
LANGS => $self->conf->{showLanguages},
|
||||
MSG => 'checkUser',
|
||||
ALERTE => 'alert-info',
|
||||
LOGIN => (
|
||||
$self->p->checkXSSAttack( 'LOGIN', $req->{user} ) ? ""
|
||||
: $req->{user}
|
||||
),
|
||||
TOKEN => (
|
||||
PORTAL => $self->conf->{portal},
|
||||
MAIN_LOGO => $self->conf->{portalMainLogo},
|
||||
LANGS => $self->conf->{showLanguages},
|
||||
MSG => 'checkUser',
|
||||
ALERTE => 'alert-info',
|
||||
LOGIN => $req->{userData}->{uid},
|
||||
ATTRIBUTES => $array_attrs->[2],
|
||||
MACROS => $array_attrs->[1],
|
||||
GROUPS => $array_attrs->[0],
|
||||
TOKEN => (
|
||||
$self->conf->{requireToken}
|
||||
? $self->ott->createToken( $req->userData )
|
||||
: ''
|
||||
|
@ -244,11 +288,24 @@ sub _userDatas {
|
|||
if ( my $error = $self->p->process($req) ) {
|
||||
if ( $error == PE_BADCREDENTIALS ) {
|
||||
$self->userLogger->warn(
|
||||
'Check requested for an unvalid user (' . $req->{user} . ")" );
|
||||
'checkUser requested for an unvalid user ('
|
||||
. $req->{user}
|
||||
. ")" );
|
||||
}
|
||||
$self->logger->debug("Process returned error: $error");
|
||||
return $req->error($error);
|
||||
}
|
||||
|
||||
# Check identities rule
|
||||
unless ( $self->idRule->( $req, $req->sessionInfo ) ) {
|
||||
$self->userLogger->warn(
|
||||
'checkUser requested for an unvalid user (' . $req->{user} . ")" );
|
||||
$req->{sessionInfo} = {};
|
||||
$self->logger->debug('Identity not authorized');
|
||||
return $req->error(PE_BADCREDENTIALS);
|
||||
}
|
||||
|
||||
$self->logger->debug("Return \"$req->{user}\" sessionInfo");
|
||||
return $req->{sessionInfo};
|
||||
}
|
||||
|
||||
|
@ -266,6 +323,8 @@ sub _authorization {
|
|||
last;
|
||||
}
|
||||
}
|
||||
|
||||
$self->logger->debug("Return \"$req->{user}\" authorization");
|
||||
return $exist
|
||||
? $self->p->HANDLER->grant( $req, $req->{userData}, $appuri,
|
||||
undef, $vhost )
|
||||
|
@ -278,6 +337,8 @@ sub _headers {
|
|||
$vhost =~ s/:\d+$//;
|
||||
$req->{env}->{HTTP_HOST} = $vhost;
|
||||
$self->p->HANDLER->headersInit( $self->{conf} );
|
||||
|
||||
$self->logger->debug("Return \"$req->{user}\" headers");
|
||||
return $self->p->HANDLER->checkHeaders( $req, $req->{userData} );
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@ extends 'Lemonldap::NG::Portal::Main::Plugin';
|
|||
|
||||
use constant endAuth => 'run';
|
||||
|
||||
has rule => ( is => 'rw', default => sub { 1 } );
|
||||
has rule => ( is => 'rw', default => sub { 1 } );
|
||||
has idRule => ( is => 'rw', default => sub { 1 } );
|
||||
|
||||
sub hAttr {
|
||||
$_[0]->{conf}->{impersonationHiddenAttributes} . ' '
|
||||
|
@ -22,11 +23,11 @@ sub hAttr {
|
|||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
my $hd = $self->p->HANDLER;
|
||||
|
||||
# Parse activation rule
|
||||
my $hd = $self->p->HANDLER;
|
||||
$self->logger->debug(
|
||||
"impersonation rule -> " . $self->conf->{impersonationRule} );
|
||||
"Impersonation rule -> " . $self->conf->{impersonationRule} );
|
||||
my $rule =
|
||||
$hd->buildSub( $hd->substitute( $self->conf->{impersonationRule} ) );
|
||||
unless ($rule) {
|
||||
|
@ -34,6 +35,19 @@ sub init {
|
|||
return 0;
|
||||
}
|
||||
$self->{rule} = $rule;
|
||||
|
||||
# Parse identity rule
|
||||
$self->logger->debug( "Impersonation identities rule -> "
|
||||
. $self->conf->{impersonationIdRule} );
|
||||
$rule =
|
||||
$hd->buildSub( $hd->substitute( $self->conf->{impersonationIdRule} ) );
|
||||
unless ($rule) {
|
||||
$self->error(
|
||||
"Bad impersonation identities rule -> " . $hd->tsv->{jail}->error );
|
||||
return 0;
|
||||
}
|
||||
$self->{idRule} = $rule;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -41,26 +55,30 @@ sub init {
|
|||
|
||||
sub run {
|
||||
my ( $self, $req ) = @_;
|
||||
my $spoofId = $req->param('spoofId') || $req->{user};
|
||||
$self->logger->debug("No impersonation required") if ( $spoofId eq $req->{user} );
|
||||
my $statut = PE_OK;
|
||||
|
||||
my $spoofId = $req->param('spoofId') || '';
|
||||
if ( $spoofId
|
||||
and $req->param('spoofId') !~ /$self->{conf}->{userControl}/o )
|
||||
{
|
||||
return PE_MALFORMEDUSER;
|
||||
if ( $spoofId !~ /$self->{conf}->{userControl}/o ) {
|
||||
$self->userLogger->error('Malformed spoofed Id');
|
||||
$self->logger->debug("Impersonation tried with spoofed Id: $spoofId");
|
||||
$spoofId = $req->{user};
|
||||
$statut = PE_MALFORMEDUSER;
|
||||
}
|
||||
|
||||
# Skip if no submitted SpoofId
|
||||
return PE_OK unless $spoofId;
|
||||
|
||||
# Check activation rule
|
||||
unless ( $self->rule->( $req, $req->sessionInfo ) ) {
|
||||
$self->userLogger->error('Impersonation service not authorized');
|
||||
return PE_IMPERSONATION_SERVICE_NOT_ALLOWED;
|
||||
if ( $spoofId ne $req->{user} ) {
|
||||
$self->logger->debug("Spoofied Id: $spoofId / Real Id: $req->{user}");
|
||||
unless ( $self->rule->( $req, $req->sessionInfo ) ) {
|
||||
$self->userLogger->error('Impersonation service not authorized');
|
||||
$spoofId = $req->{user};
|
||||
$statut = PE_IMPERSONATION_SERVICE_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
|
||||
# Fill spoof session
|
||||
my ( $realSession, $spoofSession ) = ( {}, {} );
|
||||
$self->logger->debug("Spoofing Id: $spoofId...");
|
||||
$self->logger->debug("Rename real attributes...");
|
||||
my $spk = '';
|
||||
foreach my $k ( keys %{ $req->{sessionInfo} } ) {
|
||||
if ( $self->{conf}->{impersonationSkipEmptyValues} ) {
|
||||
|
@ -74,11 +92,27 @@ sub run {
|
|||
$self->logger->debug("Delete $k");
|
||||
delete $req->{sessionInfo}->{$k};
|
||||
}
|
||||
$req->{user} = $spoofId;
|
||||
$spoofSession = $self->_userDatas($req);
|
||||
$spoofSession->{groups} ||= '';
|
||||
|
||||
# Merging SSO groups and hGroups & Dedup
|
||||
$spoofSession = $self->_userDatas( $req, $spoofId, $realSession );
|
||||
if ( $req->error ) {
|
||||
if ( $req->error == PE_BADCREDENTIALS ) {
|
||||
$statut = PE_BADCREDENTIALS;
|
||||
}
|
||||
else {
|
||||
return $req->error;
|
||||
}
|
||||
}
|
||||
|
||||
# Update spoofed session
|
||||
$self->logger->debug("Populating spoofed session...");
|
||||
foreach (qw (_auth _userDB)) {
|
||||
$self->logger->debug("Processing $_...");
|
||||
$spk = "$self->{conf}->{impersonationPrefix}$_";
|
||||
$spoofSession->{$_} = $realSession->{$spk};
|
||||
}
|
||||
|
||||
# Merging SSO Groups and hGroups & dedup
|
||||
$spoofSession->{groups} ||= '';
|
||||
if ( $self->{conf}->{impersonationMergeSSOgroups} ) {
|
||||
$self->userLogger->warn("MERGING SSO groups and hGroups...");
|
||||
my $spg = "$self->{conf}->{impersonationPrefix}groups";
|
||||
|
@ -101,22 +135,19 @@ sub run {
|
|||
{ %{ $spoofSession->{hGroups} }, %{ $realSession->{$sphg} } };
|
||||
}
|
||||
|
||||
# Create spoofed session
|
||||
foreach (qw (_auth _userDB)) {
|
||||
$self->logger->debug("Processing $_...");
|
||||
$spk = "$self->{conf}->{impersonationPrefix}$_";
|
||||
$spoofSession->{$_} = $realSession->{$spk};
|
||||
}
|
||||
$spoofSession = { %$spoofSession, %$realSession };
|
||||
|
||||
# Main session
|
||||
$self->p->updateSession( $req, $spoofSession );
|
||||
return PE_OK;
|
||||
return $statut;
|
||||
}
|
||||
|
||||
sub _userDatas {
|
||||
my ( $self, $req ) = @_;
|
||||
$req->{sessionInfo} = {};
|
||||
my ( $self, $req, $spoofId, $realSession ) = @_;
|
||||
my $realId = $req->{user};
|
||||
$req->{user} = $spoofId;
|
||||
my $raz = 0;
|
||||
|
||||
# Compute Macros and Groups with real and spoofed sessions
|
||||
$req->{sessionInfo} = {%$realSession};
|
||||
|
||||
# Search user in database
|
||||
$req->steps( [
|
||||
|
@ -133,9 +164,41 @@ sub _userDatas {
|
|||
. ")" );
|
||||
}
|
||||
$self->logger->debug("Process returned error: $error");
|
||||
return $req->error($error);
|
||||
$req->error($error);
|
||||
$raz = 1;
|
||||
}
|
||||
$self->logger->debug("Populating spoofed session...");
|
||||
|
||||
# Check identity rule if impersonation required
|
||||
if ( $realId ne $spoofId ) {
|
||||
unless ( $self->idRule->( $req, $req->sessionInfo ) ) {
|
||||
$self->userLogger->warn(
|
||||
'Impersonation requested for an unvalid user ('
|
||||
. $req->{user}
|
||||
. ")" );
|
||||
$self->logger->debug('Identity not authorized');
|
||||
$raz = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Same real and spoofed session - Compute Macros and Groups
|
||||
if ($raz) {
|
||||
$req->{sessionInfo} = {};
|
||||
$req->{sessionInfo} = {%$realSession};
|
||||
$req->{user} = $realId;
|
||||
$req->steps( [
|
||||
'getUser', 'setSessionInfo',
|
||||
'setMacros', 'setGroups',
|
||||
'setLocalGroups'
|
||||
]
|
||||
);
|
||||
$self->logger->debug('Spoofed session equal real session');
|
||||
$req->error(PE_BADCREDENTIALS);
|
||||
if ( my $error = $self->p->process($req) ) {
|
||||
$self->logger->debug("Process returned error: $error");
|
||||
$req->error($error);
|
||||
}
|
||||
}
|
||||
|
||||
return $req->{sessionInfo};
|
||||
}
|
||||
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"التحقق",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"انتظر",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"تحذير",
|
||||
"welcomeOnPortal":"مرحبا بك على بوابة إثبات الهوية الآمنة.",
|
||||
"yesResendMail":"نعم، أعد إرسال البريد",
|
||||
|
@ -258,4 +259,4 @@
|
|||
"yourPhone":"رقم هاتفك",
|
||||
"yourProfile":"ملفك الشخصي",
|
||||
"yourTotpKey":"Your TOTP key"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"Verify",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"Warten",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"Warnung",
|
||||
"welcomeOnPortal":"Willkommen in Ihrem gesicherten Authentifizierungsportal.",
|
||||
"yesResendMail":"Ja, Mail erneut senden.",
|
||||
|
@ -258,4 +259,4 @@
|
|||
"yourPhone":"Ihre Telefonnummer",
|
||||
"yourProfile":"Ihr Profil",
|
||||
"yourTotpKey":"Your TOTP key"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify": "Verify",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"Wait",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"Warning",
|
||||
"welcomeOnPortal":"Welcome on your secured authentication portal.",
|
||||
"yesResendMail":"Yes, resend the mail",
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"Verify",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"Wait",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"Warning",
|
||||
"welcomeOnPortal":"Welcome on your secured authentication portal.",
|
||||
"yesResendMail":"Yes, resend the mail",
|
||||
|
@ -258,4 +259,4 @@
|
|||
"yourPhone":"Your phone number",
|
||||
"yourProfile":"Your profile",
|
||||
"yourTotpKey":"Your TOTP key"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify": "Vérifier",
|
||||
"VHnotFound":"Hôte virtuel erroné ou inexistant",
|
||||
"wait":"Attendre",
|
||||
"waitingmessage":"Authentification en cours, merci de patienter",
|
||||
"warning":"Attention",
|
||||
"welcomeOnPortal":"Bienvenue sur votre portail d'authentification sécurisée.",
|
||||
"yesResendMail":"Oui, renvoyer le mail",
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"Verifica",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"Attendere",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"Avvertimento",
|
||||
"welcomeOnPortal":"Benvenuto sul tuo portale di autenticazione protetta.",
|
||||
"yesResendMail":"Sì, rinvia e-mail",
|
||||
|
@ -258,4 +259,4 @@
|
|||
"yourPhone":"Numero di telefono",
|
||||
"yourProfile":"Il tuo profilo",
|
||||
"yourTotpKey":"La tua chiave TOTP"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"Verify",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"Wait",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"Warning",
|
||||
"welcomeOnPortal":"Welcome on your secured authentication portal.",
|
||||
"yesResendMail":"Yes, resend the mail",
|
||||
|
@ -258,4 +259,4 @@
|
|||
"yourPhone":"Your phone number",
|
||||
"yourProfile":"Your profile",
|
||||
"yourTotpKey":"Your TOTP key"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"Verify",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"Wait",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"Warning",
|
||||
"welcomeOnPortal":"Welcome on your secured authentication portal.",
|
||||
"yesResendMail":"Yes, resend the mail",
|
||||
|
@ -258,4 +259,4 @@
|
|||
"yourPhone":"Your phone number",
|
||||
"yourProfile":"Your profile",
|
||||
"yourTotpKey":"Your TOTP key"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"Verify",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"Wait",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"Warning",
|
||||
"welcomeOnPortal":"Welcome on your secured authentication portal.",
|
||||
"yesResendMail":"Yes, resend the mail",
|
||||
|
@ -258,4 +259,4 @@
|
|||
"yourPhone":"Your phone number",
|
||||
"yourProfile":"Your profile",
|
||||
"yourTotpKey":"Your TOTP key"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"Xác minh",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"Hãy đợi",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"Cảnh báo",
|
||||
"welcomeOnPortal":"Chào mừng bạn đến với cổng thông tin xác thực được bảo mật của bạn.",
|
||||
"yesResendMail":"Có, gửi lại thư",
|
||||
|
@ -258,4 +259,4 @@
|
|||
"yourPhone":"Số điện thoại của bạn",
|
||||
"yourProfile":"Profile của bạn",
|
||||
"yourTotpKey":"Your TOTP key"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,6 +242,7 @@
|
|||
"verify":"验证",
|
||||
"VHnotFound":"Virtual Host not found",
|
||||
"wait":"等待",
|
||||
"waitingmessage":"Authentication in progress, please wait",
|
||||
"warning":"警告",
|
||||
"welcomeOnPortal":"欢迎来到您的加密认证 portal",
|
||||
"yesResendMail":"好的,重新发送邮件",
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
<TMPL_IF NAME="TOKEN">
|
||||
<input type="hidden" name="token" value="<TMPL_VAR NAME="TOKEN">" />
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_IF NAME="WAITING_MESSAGE">
|
||||
<div class="alert alert-info"><span trspan="waitingmessage" /></div>
|
||||
<TMPL_ELSE>
|
||||
<div class="form">
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
|
@ -24,9 +31,6 @@
|
|||
<input type="text" name="captcha" size="<TMPL_VAR NAME=CAPTCHA_SIZE>" class="form-control" trplaceholder="captcha" required aria-required="true" autocomplete="off" />
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
<TMPL_IF NAME="TOKEN">
|
||||
<input type="hidden" name="token" value="<TMPL_VAR NAME="TOKEN">" />
|
||||
</TMPL_IF>
|
||||
|
||||
<TMPL_INCLUDE NAME="impersonation.tpl">
|
||||
<TMPL_INCLUDE NAME="checklogins.tpl">
|
||||
|
@ -36,6 +40,7 @@
|
|||
<span trspan="connect">Connect</span>
|
||||
</button>
|
||||
</div>
|
||||
</TMPL_IF>
|
||||
|
||||
<div class="actions">
|
||||
<TMPL_IF NAME="DISPLAY_RESETPASSWORD">
|
||||
|
|
|
@ -10,7 +10,7 @@ BEGIN {
|
|||
require 't/test-lib.pm';
|
||||
}
|
||||
|
||||
my $maintests = 15;
|
||||
my $maintests = 14;
|
||||
my $debug = 'error';
|
||||
my ( $issuer, $sp, $res );
|
||||
my %handlerOR = ( issuer => [], sp => [] );
|
||||
|
@ -132,8 +132,7 @@ m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
|
|||
),
|
||||
'Get image'
|
||||
);
|
||||
ok( getHeader( $res, 'Content-Type' ) eq 'image/png', 'Get an image' )
|
||||
or explain( [ $res->[0], $res->[1] ], 'Content-Type => image/png' );
|
||||
expectRedirection( $res, "http://auth.idp.com/static/common/icons/ok.png");
|
||||
|
||||
# Test if logout is done
|
||||
switch ('issuer');
|
||||
|
|
|
@ -7,7 +7,7 @@ BEGIN {
|
|||
require 't/test-lib.pm';
|
||||
}
|
||||
|
||||
my $maintests = 3;
|
||||
my $maintests = 10;
|
||||
my $debug = 'error';
|
||||
my ( $issuer, $res );
|
||||
my %handlerOR = ( issuer => [], sp => [] );
|
||||
|
@ -25,6 +25,15 @@ SKIP: {
|
|||
ok( $res = $issuer->_get('/saml/metadata'), 'Get metadata' );
|
||||
ok( $res->[2]->[0] =~ m#^<\?xml version="1.0"\?>#s, 'Metadata is XML' );
|
||||
|
||||
ok( $res = $issuer->_get('/saml/metadata/idp'), 'Get IDP metadata' );
|
||||
ok( $res->[2]->[0] =~ m#^<\?xml version="1.0"\?>#s, 'Metadata is XML' );
|
||||
ok( $res->[2]->[0] !~ m#<SPSSODescriptor#s, 'Metadata does not contain SP information' );
|
||||
ok( $res->[2]->[0] =~ m#entityID="urn:example\.com"#s, 'IDP EntityID is overriden' );
|
||||
|
||||
ok( $res = $issuer->_get('/saml/metadata/sp'), 'Get SP metadata' );
|
||||
ok( $res->[2]->[0] =~ m#^<\?xml version="1.0"\?>#s, 'Metadata is XML' );
|
||||
ok( $res->[2]->[0] !~ m#<IDPSSODescriptor#s, 'Metadata does not contain IDP information' );
|
||||
|
||||
#print STDERR Dumper($res);
|
||||
}
|
||||
|
||||
|
@ -41,6 +50,7 @@ sub issuer {
|
|||
authentication => 'Demo',
|
||||
userDB => 'Same',
|
||||
issuerDBSAMLActivation => 1,
|
||||
samlOverrideIDPEntityID => 'urn:example.com',
|
||||
samlSPMetaDataOptions => {
|
||||
'sp.com' => {
|
||||
samlSPMetaDataOptionsEncryptionMode => 'none',
|
||||
|
|
|
@ -0,0 +1,543 @@
|
|||
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 = 21;
|
||||
my $debug = 'error';
|
||||
my ( $issuer, $sp, $res );
|
||||
my %handlerOR = ( issuer => [], sp => [] );
|
||||
|
||||
# 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;
|
||||
|
||||
# Simple SP access
|
||||
my $res;
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
'/', accept => 'text/html',
|
||||
),
|
||||
'Unauth SP request'
|
||||
);
|
||||
expectOK($res);
|
||||
ok( expectCookie( $res, 'lemonldapidp' ), 'IDP cookie defined' )
|
||||
or explain(
|
||||
$res->[1],
|
||||
'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp.com; path=/'
|
||||
);
|
||||
my ( $host, $url, $s ) =
|
||||
expectAutoPost( $res, 'auth.idp.com', '/saml/singleSignOn',
|
||||
'SAMLRequest' );
|
||||
|
||||
# Push SAML request to IdP
|
||||
switch ('issuer');
|
||||
ok(
|
||||
$res = $issuer->_post(
|
||||
$url,
|
||||
IO::String->new($s),
|
||||
accept => 'text/html',
|
||||
length => length($s)
|
||||
),
|
||||
'Post SAML request to IdP'
|
||||
);
|
||||
expectOK($res);
|
||||
my $pdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
|
||||
|
||||
# Try to authenticate with an unauthorized user to IdP
|
||||
$s = "user=dwho&password=dwho&$s";
|
||||
ok(
|
||||
$res = $issuer->_post(
|
||||
$url,
|
||||
IO::String->new($s),
|
||||
accept => 'text/html',
|
||||
cookie => $pdata,
|
||||
length => length($s),
|
||||
),
|
||||
'Post authentication'
|
||||
);
|
||||
ok( $res->[2]->[0] =~ /trmsg="89"/, 'Reject reason is 89' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
|
||||
# Simple SP access
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
'/', accept => 'text/html',
|
||||
),
|
||||
'Unauth SP request'
|
||||
);
|
||||
expectOK($res);
|
||||
ok( expectCookie( $res, 'lemonldapidp' ), 'IDP cookie defined' )
|
||||
or explain(
|
||||
$res->[1],
|
||||
'Set-Cookie => lemonldapidp=http://auth.idp.com/saml/metadata; domain=.sp.com; path=/'
|
||||
);
|
||||
( $host, $url, $s ) =
|
||||
expectAutoPost( $res, 'auth.idp.com', '/saml/singleSignOn',
|
||||
'SAMLRequest' );
|
||||
|
||||
# Push SAML request to IdP
|
||||
ok(
|
||||
$res = $issuer->_post(
|
||||
$url,
|
||||
IO::String->new($s),
|
||||
accept => 'text/html',
|
||||
length => length($s)
|
||||
),
|
||||
'Post SAML request to IdP'
|
||||
);
|
||||
expectOK($res);
|
||||
$pdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
|
||||
|
||||
# Try to authenticate with an authorized user to IdP
|
||||
$s = "user=french&password=french&$s";
|
||||
ok(
|
||||
$res = $issuer->_post(
|
||||
$url,
|
||||
IO::String->new($s),
|
||||
accept => 'text/html',
|
||||
cookie => $pdata,
|
||||
length => length($s),
|
||||
),
|
||||
'Post authentication'
|
||||
);
|
||||
my $idpId = expectCookie($res);
|
||||
( $host, $url, $s ) =
|
||||
expectAutoPost( $res, 'auth.sp.com', '/saml/proxySingleSignOnPost',
|
||||
'SAMLResponse' );
|
||||
|
||||
# Post SAML response to SP
|
||||
switch ('sp');
|
||||
ok(
|
||||
$res = $sp->_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'
|
||||
);
|
||||
|
||||
# Verify authentication on SP
|
||||
expectRedirection( $res, 'http://auth.sp.com' );
|
||||
my $spId = expectCookie($res);
|
||||
|
||||
ok( $res = $sp->_get( '/', cookie => "lemonldap=$spId" ), 'Get / on SP' );
|
||||
expectOK($res);
|
||||
expectAuthenticatedAs( $res, 'fa@badwolf.org@idp' );
|
||||
|
||||
# Verify UTF-8
|
||||
ok( $res = $sp->_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' );
|
||||
|
||||
# Logout initiated by SP
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
'/',
|
||||
query => 'logout',
|
||||
cookie => "lemonldap=$spId",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Query SP for logout'
|
||||
);
|
||||
( $host, $url, $s ) =
|
||||
expectAutoPost( $res, 'auth.idp.com', '/saml/singleLogout',
|
||||
'SAMLRequest' );
|
||||
|
||||
# Push SAML logout request to IdP
|
||||
switch ('issuer');
|
||||
ok(
|
||||
$res = $issuer->_post(
|
||||
$url,
|
||||
IO::String->new($s),
|
||||
accept => 'text/html',
|
||||
cookie => "lemonldap=$idpId",
|
||||
length => length($s)
|
||||
),
|
||||
'Post SAML logout request to IdP'
|
||||
);
|
||||
|
||||
# The SP doesn't have an SLO endpoint for its response (Hi Renater!) , in
|
||||
# this case, the portal should display a nice user message instead of
|
||||
# erroring.
|
||||
expectOK($res);
|
||||
|
||||
ok( $res->[2]->[0] =~ /trmsg="47"/, 'Found logout message' );
|
||||
|
||||
ok(
|
||||
$res = $issuer->_get(
|
||||
'/', cookie => "lemonldap=$idpId",
|
||||
),
|
||||
'Test if user is reject on IdP'
|
||||
);
|
||||
expectReject($res);
|
||||
|
||||
switch ('sp');
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
'/',
|
||||
accept => 'text/html',
|
||||
cookie =>
|
||||
"lemonldapidp=http://auth.idp.com/saml/metadata; lemonldap=$spId"
|
||||
),
|
||||
'Test if user is reject on SP'
|
||||
);
|
||||
expectOK($res);
|
||||
expectAutoPost( $res, 'auth.idp.com', '/saml/singleSignOn', 'SAMLRequest' );
|
||||
}
|
||||
|
||||
count($maintests);
|
||||
clean_sessions();
|
||||
done_testing( count() );
|
||||
|
||||
sub switch {
|
||||
my $type = shift;
|
||||
@Lemonldap::NG::Handler::Main::_onReload = @{
|
||||
$handlerOR{$type};
|
||||
};
|
||||
}
|
||||
|
||||
sub issuer {
|
||||
return LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
domain => 'idp.com',
|
||||
portal => 'http://auth.idp.com',
|
||||
authentication => 'Demo',
|
||||
userDB => 'Same',
|
||||
issuerDBSAMLActivation => 1,
|
||||
issuerDBSAMLRule => '$uid eq "french"',
|
||||
samlSPMetaDataOptions => {
|
||||
'sp.com' => {
|
||||
samlSPMetaDataOptionsEncryptionMode => 'none',
|
||||
samlSPMetaDataOptionsSignSSOMessage => 1,
|
||||
samlSPMetaDataOptionsSignSLOMessage => 1,
|
||||
samlSPMetaDataOptionsCheckSSOMessageSignature => 1,
|
||||
samlSPMetaDataOptionsCheckSLOMessageSignature => 1,
|
||||
}
|
||||
},
|
||||
samlSPMetaDataExportedAttributes => {
|
||||
'sp.com' => {
|
||||
cn =>
|
||||
'1;cn;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
|
||||
uid =>
|
||||
'1;uid;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
|
||||
}
|
||||
},
|
||||
samlOrganizationDisplayName => "IDP",
|
||||
samlOrganizationName => "IDP",
|
||||
samlOrganizationURL => "http://www.idp.com/",
|
||||
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAnfKBDG/K0TnGT7Xu8q1N45sNWvIK91SqNg8nvN2uVeKoHADT
|
||||
csus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9ryfSNDhWDWloNkpGEeWif2BnHUu46
|
||||
Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnVDNfSEASVIppEBYjDX203ypmURIzU
|
||||
6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+tBlcnMrkv/40DSUkehQIl2JmlFrl2
|
||||
Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5NMd0KFa6CwZUUSHJqH5GFy5Y2yl4l
|
||||
g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQIDAQABAoIBAHnfqjX3eO8SfnP5
|
||||
NURp90Td2mNHirCn0qLd9NKl1ySMPR1GgeH9SQ7Umu32EcteAUL5dOw2PiTZVmeW
|
||||
cKINgsWVftXUQcOQ4xIqWKb51QUBdy0FhxrZRSFjWxXt5iYK1PmzHfsax/g1/S9C
|
||||
RnqtFyjOy1bywkSt9jiy+9YBR2B7BDhLHlILbijWn5zaecaV4YA+L1UK4M/mehdb
|
||||
+0FVPavbGpnlqBRTY+7YXfZ/mRPCfn5DvO9lW1O0pJMmNdBh9kmm3DxHf6AkK47a
|
||||
43gO/dRWiWo2rZ/+Jw7uyqOb23U0MydP7kia0p3tzCUBPsrlgnichYG5RNFp0wqy
|
||||
3VT1TYECgYEA0Y9vENy1jJd+s7WbGrsRtSKxfZgtJr0yjSlQVYrIlwbZSGn+ndxq
|
||||
V2vVlwIgLX3pz6T40BMfk6SNx08jjy0Sgn6OAM0ILrinno8yWcSAMCmfCU0S/3O1
|
||||
55bqtcnk4XTHBHzJ5OrnrPaW5ourvJz0lcWEKMg3BXxLzaF6ZRy85nECgYEAwPMD
|
||||
LNAKLCDrUMyYFOpPyPLe7wvszcFvPipGgerSgFP1c6N7xaMUdHDYqBfuis1khPGF
|
||||
YcMHeNBYmzX6yEGbp3lrB4PHpUySmTU3mv3u9I05aahInK21gXum3uRkCWyyIF6V
|
||||
T/qeszl9mVOCp0CC4eG3IMVpaD0UKDEHVhERYCkCgYAjuTPRyA4a3Wh38ilysRkf
|
||||
q75eDqcDx5Tqg3RyYKo5NK2troP9HSnzpSpQB8i8eI53G0RfFCN5479XjqIdMi3J
|
||||
mRFUCZ+vd0L7wKVwsBK6Ix49U6o9adhElnGEc9pUpLeYiD1SjMjZr1+iBYVNLeRz
|
||||
86vH1/mpMbsqXrCis/dvwQKBgGttomHr/w3s0jftget7PirrFrbP0+wHfDGHhjRF
|
||||
kyhCFtJovrwefYALaIXGtVjw3LusYZA570oT7pGUb2naJZkMYEwR0jG1vZWx7KDO
|
||||
K6JbkxDB0pPxn7JVL2bAkPYyX8boAohCSOQO6WBZ/8+xem3bp4OGhpa0EyoBik0g
|
||||
OaVpAoGATj4SyYsE10hGT676iie8zy3fi5IPC3E+x4QlVuusaLtuY8LJA50stjtx
|
||||
gUa/JAKlZZL+gvzvOviQIxyfIChXOdTt5uiOYkdHJDbAF3NSrji7hrXq4v8UZv75
|
||||
8hBrwJZIpy6y01dRlrriHmPRtEq1pk7JX2uUg0sP5g4BEcsaCbc=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAtR/wgDqWB4Maho5V6TjcL/NbNfjgIh7GcgkrB5RZcVT1GTej
|
||||
JlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6S8SpeJ1ofp5rBEoD/TIkvU0JOcid
|
||||
65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRyBIQzB0SIxSpnrsigqNsE1E94toDM
|
||||
x4wovjHu/9ABAImREV7Sz83OeFF00/sghrjTEJOD/gHf04JCn9MgNOqvSTysr9LX
|
||||
Wg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5yD41mi+hT8Rh+W8Je8rsiML4VMxz
|
||||
sb1l9303asw6suo5bLTISKNSbu1nt1NkpNxzywIDAQABAoIBAQCQkbvPPfP+bwC/
|
||||
IeEk1IO7qkzFWa7czR+safD0jc6OjTdNN4F716Q6yt4zEzLKu8VliiW+C23EBQiD
|
||||
7asKf4DvdTun0ExVtHDK7aEdeealSlXwz1ZtdypyILbtq1UGo/rR0v4x601rQPl0
|
||||
IrBmFf6D6FkqleNtLJmxguXpoVfLdYKNwkxH2ux+GOA9r2o5pUCQmJGDap5YWRuQ
|
||||
uB71ewJjVWujaL3e1ac/5cP7/tqWmgAiOaN8sYdD6+oWOR47bHj8JKcMBSl4y2QC
|
||||
dL31cGmmf5KqBbtISki3RXfHHjT7E3Z85CbESkKTZlEb1ar3XmepY6Z7V5UO16oz
|
||||
fFE5R6khAoGBAOl9Qb+qYVVO5ugE65ORjYVeuXykANhM9ssiY5a6zuAakWzw7Zv3
|
||||
k6PXm9p7azlEXAlTnTXVwHYMyuuzZDvQ8LRV1iBOdPuIkUAmaQ5K9ASD7VcoHexh
|
||||
k8DAKf9Ln7sTRaMdvgceRNczOmJOBIEpTZkssA/jVGXZsoyTWYl1en/ZAoGBAMaW
|
||||
RnNbSNprEV2b8UeAJ6i77c4SXwu1I8X2NLtiLScb1ETBjfrdHmdlJglfyd/0gmhH
|
||||
p/43Ku2iGUoY5KtuOI6QmahrJYQscRQhoj252VXadG6fNWWAlpgdCm9houhHb5BF
|
||||
3zge/bTr0anUe9EA7Z/ymav12rEouoNjIlhI9C5DAoGATR85a2SMt8/TB0owwdJu
|
||||
62GpZNkLCmcJkXkvaecUVAOSi2hdI4o4MwMRkK35cbX5rH74y4JqCtQY5pefgP53
|
||||
sykzDAK+MyMdzxGg2764MRGegI5Yq+5jDmSquo+xF+q6srEtRk6iMG7UVwosBLmu
|
||||
zuxqzySoiOfKSRKWnYe3SakCgYEAwWMkVkAmETXE4oDzFSsS8/mW2l//mPocTTK3
|
||||
JWe1CunJ6+8FYbAlZJEW2ngismp8+CoXybNVpbZ+pC7buKoMf6EHUgCNt0pEEFO0
|
||||
mCG9KSMk0XlPWXpArP9S4yaUq1itpzSz7QYZES+4rIcU0HLz9RgeWFyCTJWaFErc
|
||||
7laVG9sCgYBKOtk5WlIOP4BxSd2y4cYzohgwTZIs1/2kTEn1u4eH73M1xvAlHHFB
|
||||
wSF5QXgDKJ8pPAOhNWpdLO/PdtnQn91nOvTNc+ShJZzjdbneUdQVpWpoBf72uA+N
|
||||
6rIVf1JBUL2p7HFHaGdUZC7KGQ+yv6ZHrE1+7202nuDvJdvGEEdFsQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnfKBDG/K0TnGT7Xu8q1N
|
||||
45sNWvIK91SqNg8nvN2uVeKoHADTcsus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9r
|
||||
yfSNDhWDWloNkpGEeWif2BnHUu46Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnV
|
||||
DNfSEASVIppEBYjDX203ypmURIzU6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+t
|
||||
BlcnMrkv/40DSUkehQIl2JmlFrl2Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5N
|
||||
Md0KFa6CwZUUSHJqH5GFy5Y2yl4lg8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxI
|
||||
GQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtR/wgDqWB4Maho5V6Tjc
|
||||
L/NbNfjgIh7GcgkrB5RZcVT1GTejJlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6
|
||||
S8SpeJ1ofp5rBEoD/TIkvU0JOcid65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRy
|
||||
BIQzB0SIxSpnrsigqNsE1E94toDMx4wovjHu/9ABAImREV7Sz83OeFF00/sghrjT
|
||||
EJOD/gHf04JCn9MgNOqvSTysr9LXWg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5
|
||||
yD41mi+hT8Rh+W8Je8rsiML4VMxzsb1l9303asw6suo5bLTISKNSbu1nt1NkpNxz
|
||||
ywIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlSPMetaDataXML => {
|
||||
"sp.com" => {
|
||||
samlSPMetaDataXML => <<EOF
|
||||
<?xml version="1.0"?>
|
||||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="http://auth.sp.com/saml/metadata">
|
||||
<SPSSODescriptor AuthnRequestsSigned="true"
|
||||
WantAssertionsSigned="true"
|
||||
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
|
||||
<KeyDescriptor use="signing">
|
||||
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
||||
<ds:KeyValue>
|
||||
<RSAKeyValue xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<Modulus>
|
||||
u4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr
|
||||
+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX
|
||||
7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGS
|
||||
RSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
|
||||
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9Nqw==</Modulus>
|
||||
<Exponent>AQAB</Exponent>
|
||||
</RSAKeyValue>
|
||||
</ds:KeyValue>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
<KeyDescriptor use="encryption">
|
||||
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
||||
<ds:KeyValue>
|
||||
<RSAKeyValue xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||
<Modulus>
|
||||
sRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Us
|
||||
og3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVL
|
||||
R+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8r
|
||||
UWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
|
||||
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+w==</Modulus>
|
||||
<Exponent>AQAB</Exponent>
|
||||
</RSAKeyValue>
|
||||
</ds:KeyValue>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
<ArtifactResolutionService isDefault="true" index="0"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
|
||||
Location="http://auth.sp.com/saml/artifact" />
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:2.0:nameid-format:entity</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||
<AssertionConsumerService isDefault="true" index="0"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="http://auth.sp.com/saml/proxySingleSignOnPost" />
|
||||
<AssertionConsumerService isDefault="false" index="1"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
|
||||
Location="http://auth.sp.com/saml/proxySingleSignOnArtifact" />
|
||||
</SPSSODescriptor>
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">org</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en">
|
||||
org</OrganizationDisplayName>
|
||||
<OrganizationURL xml:lang="en">
|
||||
http://www.org.com</OrganizationURL>
|
||||
</Organization>
|
||||
</EntityDescriptor>
|
||||
EOF
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub sp {
|
||||
return LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
domain => 'sp.com',
|
||||
portal => 'http://auth.sp.com',
|
||||
authentication => 'SAML',
|
||||
userDB => 'Same',
|
||||
issuerDBSAMLActivation => 0,
|
||||
restSessionServer => 1,
|
||||
samlIDPMetaDataExportedAttributes => {
|
||||
idp => {
|
||||
mail => "0;mail;;",
|
||||
uid => "1;uid",
|
||||
cn => "0;cn"
|
||||
}
|
||||
},
|
||||
samlIDPMetaDataOptions => {
|
||||
idp => {
|
||||
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
||||
samlIDPMetaDataOptionsSSOBinding => 'post',
|
||||
samlIDPMetaDataOptionsSLOBinding => 'post',
|
||||
samlIDPMetaDataOptionsSignSSOMessage => 1,
|
||||
samlIDPMetaDataOptionsSignSLOMessage => 1,
|
||||
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsForceUTF8 => 1,
|
||||
}
|
||||
},
|
||||
samlIDPMetaDataExportedAttributes => {
|
||||
idp => {
|
||||
"uid" => "0;uid;;",
|
||||
"cn" => "1;cn;;",
|
||||
},
|
||||
},
|
||||
samlIDPMetaDataXML => {
|
||||
idp => {
|
||||
samlIDPMetaDataXML =>
|
||||
samlIDPMetaDataXML( 'idp', 'HTTP-POST' )
|
||||
}
|
||||
},
|
||||
samlOrganizationDisplayName => "SP",
|
||||
samlOrganizationName => "SP",
|
||||
samlOrganizationURL => "http://www.sp.com",
|
||||
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4iToYAEmWQxgZDihGVz
|
||||
MMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKR
|
||||
FXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJ
|
||||
GZNX7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTja
|
||||
Sxsp4UndTI8/+mGSRSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAq
|
||||
Cq8odmbI0yCRZiTL9ybKWRKqWJoKJ0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9N
|
||||
qwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAsRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiG
|
||||
e/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIl
|
||||
l0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVLR+QUm+/1LIKYb3OCBTvOlY7x
|
||||
HoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8rUWRZbbDn31Tm
|
||||
Kjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
|
||||
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+wIDAQABAoIBAEkZrk8iiJKJ0WAx
|
||||
IrsyKNbXuWKLTYgnxcRCyzKofrfID+YcU39j8JeI0fKbajQUZ7qhnlTLwtU//+2h
|
||||
SqzyVu6/add/v7ZRWQw3L7cGzKK2THHzKVtLk/t7N3QroDdf1LMrQvkFP2HmcWS0
|
||||
/yN62hXtXHb/qpY4Nn+6JQyUpM5dkv8S/QjDl2NTdyWrXKzWp+4I3QLQ20f4zym+
|
||||
ir7RennziMc0HlQNcTjGAUbFULtdqEfSFWhNK7UjiRY+S0XV2xJIbGjnxUQH62fS
|
||||
w1ZzYsF7sBtoSckvfL4WfGbylhOVnliU05RLU2c67PRjj1Gskoslq1Ow/3DHR7rI
|
||||
BSBpV8ECgYEA1eHfcog7xQGDkW+cshJtFPFx+9MegB58gFW1rl0rn+tfbexvoSEA
|
||||
7G7EOTyaU6OAI+8StiRT6AYTgEU7PMM9zDykdGIWj3h0OpHGA86xhEiiaaM2DDRv
|
||||
/DEKRVlEdmRLLLY28pJVHOMYomia3mb2VKZGg2VfGtSfjg1GXD3I8OECgYEA0/X0
|
||||
U55KjZ1JQTPUgFc1WK1NxX9MaH+NcpDaolEUy3Qf3QTbfws+a9K3vwCn7EpQhrfs
|
||||
I6RVUtwFdCyfl/jzBY9Gykkg03sMgW7Qw2SCCsSt05M+jDtBbNJ7esP6PAeKFvXZ
|
||||
ZWhdeiAa4kM/P6gtvZXQ4tY4LkSbcd6b0SzzFFsCgYBjMsusFzuBd95JyfZnMNye
|
||||
5gzzu0teKMWd0CLfqB7foQ81sH9lwCTpg8ZGtbDuMdrwz6ViDR9NceQBjhqXaAZ1
|
||||
f3rW79d+22Ms9wdcJLV4oSeSzzv2FSwLT8NvvqNeNc4YArshbnVDXKDEUrfhhueh
|
||||
Ay2ZK58clpkaDVYg2hckgQKBgG3KuhtSI/YE4fwXN9yez7A2XNGPZem/IGqWo9lu
|
||||
PGJCrXqT2IqPLW82gB083r6jo+CUhonTxqqb82tA7g4PUvqvQ5Dmnk1NMKYe255K
|
||||
gp3HUO8GF2EWFIak5Hcr6oOLuDi6cjh3/euTk7ld8fYsTD0mzEOjiQhWW1p5X6bT
|
||||
LLp/AoGAHvkxA1NM1HJ3myAREbwNXxRy/nhNt4mwMkZ6hPQsW/Eg/3r7j6MJOFrm
|
||||
U8AJJjDGKe6nlXhhnMoQfJzAc0cYNgjktmJXW27fHGIwt/2QwYNFHPK3s7HTrfH6
|
||||
7T4XKT3yGeeeyC2soKJQPlGB+ETdIUnXa7eo9KVWtMTgISyx1Qk=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAu4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh
|
||||
5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsC
|
||||
uDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX7bglfEc9+QQpYTqN1rkdN1PV
|
||||
U0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGSRSq+nrT2zyQR
|
||||
M/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
|
||||
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9NqwIDAQABAoIBABE0Cjb6g3F+23vD
|
||||
SsRSeiqzrFrfOEqtXK+VGrfWzHS7V7Ozg6eW/H+HGJXUzUuQcklfg7EFA3JB41a0
|
||||
GxW3oA+UElkfCV/dcAG5NbRqGQKScEz9glZb5FikgDLqiPP+HabS/gvQSu71t2HI
|
||||
3KxSRJdwCNTp26Z28pxxYUpmELTtxd9vlHjffit2Mnt2uc8hOtFHdNavfYwvYH7o
|
||||
bmlckp7b/JVOy2Yy21O94ZWkE498jXyn71Gr+V1cnJ0RrmYbhQqIvFpFHj98Pf4O
|
||||
if3c4YmBcZ4t7PUsZUYF3ooWt8k/mdigQC3D6p80OKe+wUTYKcCN0ZdFbiURv9pg
|
||||
CsqLh+ECgYEA9vA+9QfzvXC7S5yXgTkuRiusPlNye/AiyA/0oGjmjFZ1YNsT7awH
|
||||
6BjW6WE+rS4elKJu1GaefM/cDguH4ZmJc+eKgi4LDCqYw9rr9les3aneBc8demd3
|
||||
O/Ej1Pud1QxXArBNfBYo08vEqwST9P89clJC5090U6bGK2E0rTVu1w0CgYEAwmpG
|
||||
9LbOFeGCPmwX7Avuk7tQQfRSV6q9TFZo+HxDfKYvxec846l1vBenY2rrgYhtolYJ
|
||||
YS795LYgbSWRxGfgr1GuIbP5GsjHy6/1o6bS8M++GJ7KHArb0QLAYyQweqqb164A
|
||||
NvHJkveueWnxzeOlD9j2fcjEnBHwTnqjG+17CZcCgYEAqMXawa4FsNxzpmIISpHC
|
||||
RsNindZ60Kp3mzUMhPYtXI1a/C+/lxmU7dTMTgXgyIxU6lF6XkEk4TlPtWm8HTzK
|
||||
7SS7Te4aLt6OOo5N57hUtct7q4y7IQXGQHm3e8HdRdeBQJ0u2Dhs/xSt/hTK6w/n
|
||||
91Kx11Y+s02w88UkM53pe6ECgYAF/UYwVc1liSv9BlF6WSfBb1zam09KGh1405Sq
|
||||
SxG9LlV8cFJE5TyWTdg/TNTyiaRvAt2JG+yAdkfrdOPXvCeE3yxRJ30+IP9evA4C
|
||||
O6p19sBxe7rYQFFjUAVjSIMh1E22yEqDZtGB8JV0chob8K5uHY4CdAPylu7jTA3o
|
||||
V1maAwKBgQCSGQ3yzsk4EGN2xd/JdgGDzhKyTZTQKMWYqQcsYxRAQ7Paj7u+Wkgv
|
||||
dBeKcI0HwgpLy5ZohSd2erqieIsW0pEbJWCmos4IcO8tgNfEOa5WXYdyLbj5tFwt
|
||||
ctu4/BJdijqfpMAtG8pv6k09gYjfASVytXmydGcs/0rVKYCRQA8Tow==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRaod2RZ8hMFBl+Vhsnh
|
||||
yPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpi
|
||||
jpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6
|
||||
jLVLR+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1
|
||||
zO0njuqGHkwEpy8rUWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtY
|
||||
XVhuG8OrWQDoS5gYHSjdw1CTJyixeJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz
|
||||
+wIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlSPSSODescriptorAuthnRequestsSigned => 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,502 @@
|
|||
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 = 12;
|
||||
my $debug = 'error';
|
||||
my ( $idp, $proxy, $app, $res );
|
||||
my %handlerOR = ( idp => [], proxy => [], app => [] );
|
||||
|
||||
# Redefine LWP methods for tests
|
||||
LWP::Protocol::PSGI->register(
|
||||
sub {
|
||||
my $req = Plack::Request->new(@_);
|
||||
ok( $req->uri =~ m#http://auth.(app|proxy).com([^\?]*)(?:\?(.*))?$#,
|
||||
'SOAP request' );
|
||||
my $host = $1;
|
||||
my $url = $2;
|
||||
my $query = $3;
|
||||
my $res;
|
||||
my $client = ( $host eq 'app' ? $app : $proxy );
|
||||
if ( $req->method eq 'POST' ) {
|
||||
my $s = $req->content;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
$url, IO::String->new($s),
|
||||
length => length($s),
|
||||
query => $query,
|
||||
type => 'application/xml',
|
||||
),
|
||||
"Execute POST request to $url"
|
||||
);
|
||||
}
|
||||
else {
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
$url,
|
||||
type => 'application/xml',
|
||||
query => $query,
|
||||
),
|
||||
"Execute request to $url"
|
||||
);
|
||||
}
|
||||
expectOK($res);
|
||||
ok( getHeader( $res, 'Content-Type' ) =~ m#xml#, 'Content is XML' )
|
||||
or explain( $res->[1], 'Content-Type => application/xml' );
|
||||
count(3);
|
||||
return $res;
|
||||
}
|
||||
);
|
||||
|
||||
SKIP: {
|
||||
eval "use Lasso";
|
||||
if ($@) {
|
||||
skip 'Lasso not found', $maintests;
|
||||
}
|
||||
|
||||
# Initialization
|
||||
switch ('idp');
|
||||
ok( $idp = idp(), 'IdP portal' );
|
||||
$handlerOR{idp} = \@Lemonldap::NG::Handler::Main::_onReload;
|
||||
|
||||
switch ('proxy');
|
||||
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
|
||||
ok( $proxy = proxy(), 'Proxy portal' );
|
||||
$handlerOR{proxy} = \@Lemonldap::NG::Handler::Main::_onReload;
|
||||
|
||||
switch ('app');
|
||||
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
|
||||
ok( $app = app(), 'CAS app portal' );
|
||||
$handlerOR{app} = \@Lemonldap::NG::Handler::Main::_onReload;
|
||||
|
||||
# Query RP for auth
|
||||
ok( $res = $app->_get( '/', accept => 'text/html' ),
|
||||
'Unauth CAS app request' );
|
||||
ok( expectCookie( $res, 'llngcasserver' ) eq 'proxy',
|
||||
'Get CAS server cookie' );
|
||||
my ( $url, $query ) =
|
||||
expectRedirection( $res, qr#http://auth.proxy.com(/cas/login)\?(.*)$# );
|
||||
|
||||
# Push request to Proxy
|
||||
switch ('proxy');
|
||||
ok(
|
||||
$res = $proxy->_get(
|
||||
$url,
|
||||
query => $query,
|
||||
accept => 'text/html',
|
||||
),
|
||||
"Push request to proxy"
|
||||
);
|
||||
my $proxyPdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
|
||||
|
||||
my ( $url, $query ) =
|
||||
expectRedirection( $res, qr#^http://discovery.example.com/# );
|
||||
|
||||
# Return from WAYF
|
||||
ok(
|
||||
$res = $proxy->_get(
|
||||
"/",
|
||||
query => "idp=".uri_escape("http://auth.idp.com/saml/metadata"),
|
||||
accept => 'text/html',
|
||||
cookie => $proxyPdata,
|
||||
),
|
||||
"Return from WAYF"
|
||||
);
|
||||
|
||||
$proxyPdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
|
||||
|
||||
my ( $host, $tmp );
|
||||
( $host, $url, $query ) =
|
||||
expectAutoPost( $res, 'auth.idp.com', '/saml/singleSignOn',
|
||||
'SAMLRequest' );
|
||||
|
||||
switch ('idp');
|
||||
ok(
|
||||
$res = $idp->_post(
|
||||
$url,
|
||||
IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Launch SAML request to IdP'
|
||||
);
|
||||
my $idpPdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
|
||||
|
||||
# Try to authenticate to IdP
|
||||
my $body = $res->[2]->[0];
|
||||
$body =~ s/^.*?<form.*?>//s;
|
||||
$body =~ s#</form>.*$##s;
|
||||
my %fields =
|
||||
( $body =~ /<input type="hidden".+?name="(.+?)".+?value="(.*?)"/sg );
|
||||
$fields{user} = $fields{password} = 'french';
|
||||
use URI::Escape;
|
||||
$query =
|
||||
join( '&', map { "$_=" . uri_escape( $fields{$_} ) } keys %fields );
|
||||
ok(
|
||||
$res = $idp->_post(
|
||||
$url,
|
||||
IO::String->new($query),
|
||||
accept => 'text/html',
|
||||
length => length($query),
|
||||
cookie => $idpPdata,
|
||||
),
|
||||
'Post authentication'
|
||||
);
|
||||
|
||||
( $host, $url, $query ) = expectAutoPost($res);
|
||||
$query =~ s/\+/%2B/g;
|
||||
my $idpId = expectCookie($res);
|
||||
|
||||
# Post SAML response
|
||||
switch ('proxy');
|
||||
ok(
|
||||
$res = $proxy->_post(
|
||||
$url, IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
cookie =>
|
||||
"lemonldapidp=http://auth.idp.com/saml/metadata;$proxyPdata",
|
||||
),
|
||||
'POST SAML response'
|
||||
);
|
||||
my $spId = expectCookie($res);
|
||||
($url) = expectRedirection( $res, qr#http://auth.proxy.com([^?]*)# );
|
||||
ok(
|
||||
$res = $proxy->_get(
|
||||
$url,
|
||||
accept => 'text/html',
|
||||
cookie =>
|
||||
"lemonldapidp=http://auth.idp.com/saml/metadata;lemonldap=$spId;$proxyPdata",
|
||||
),
|
||||
'Follow internal redirection'
|
||||
);
|
||||
|
||||
($query) =
|
||||
expectRedirection( $res, qr#^http://auth.app.com/\?(ticket.*)$# );
|
||||
|
||||
# Follow redirection to App
|
||||
switch ('app');
|
||||
ok( $res = $app->_get( '/', query => $query, accept => 'text/html' ),
|
||||
'Follow redirection to RP' );
|
||||
my $appId = expectCookie($res);
|
||||
}
|
||||
|
||||
count($maintests);
|
||||
clean_sessions();
|
||||
done_testing( count() );
|
||||
|
||||
sub switch {
|
||||
my $type = shift;
|
||||
pass( '==> Switching to ' . uc($type) . ' <==' );
|
||||
count(1);
|
||||
@Lemonldap::NG::Handler::Main::_onReload = @{
|
||||
$handlerOR{$type};
|
||||
};
|
||||
}
|
||||
|
||||
sub idp {
|
||||
return LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
domain => 'idp.com',
|
||||
portal => 'http://auth.idp.com',
|
||||
authentication => 'Demo',
|
||||
userDB => 'Same',
|
||||
issuerDBSAMLActivation => 1,
|
||||
samlSPMetaDataOptions => {
|
||||
'proxy.com' => {
|
||||
samlSPMetaDataOptionsEncryptionMode => 'none',
|
||||
samlSPMetaDataOptionsSignSSOMessage => 1,
|
||||
samlSPMetaDataOptionsSignSLOMessage => 1,
|
||||
samlSPMetaDataOptionsCheckSSOMessageSignature => 1,
|
||||
samlSPMetaDataOptionsCheckSLOMessageSignature => 1,
|
||||
}
|
||||
},
|
||||
samlSPMetaDataExportedAttributes => {
|
||||
'proxy.com' => {
|
||||
cn =>
|
||||
'1;cn;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
|
||||
uid =>
|
||||
'1;uid;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
|
||||
}
|
||||
},
|
||||
samlOrganizationDisplayName => "IDP",
|
||||
samlOrganizationName => "IDP",
|
||||
samlOrganizationURL => "http://www.idp.com/",
|
||||
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAnfKBDG/K0TnGT7Xu8q1N45sNWvIK91SqNg8nvN2uVeKoHADT
|
||||
csus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9ryfSNDhWDWloNkpGEeWif2BnHUu46
|
||||
Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnVDNfSEASVIppEBYjDX203ypmURIzU
|
||||
6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+tBlcnMrkv/40DSUkehQIl2JmlFrl2
|
||||
Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5NMd0KFa6CwZUUSHJqH5GFy5Y2yl4l
|
||||
g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQIDAQABAoIBAHnfqjX3eO8SfnP5
|
||||
NURp90Td2mNHirCn0qLd9NKl1ySMPR1GgeH9SQ7Umu32EcteAUL5dOw2PiTZVmeW
|
||||
cKINgsWVftXUQcOQ4xIqWKb51QUBdy0FhxrZRSFjWxXt5iYK1PmzHfsax/g1/S9C
|
||||
RnqtFyjOy1bywkSt9jiy+9YBR2B7BDhLHlILbijWn5zaecaV4YA+L1UK4M/mehdb
|
||||
+0FVPavbGpnlqBRTY+7YXfZ/mRPCfn5DvO9lW1O0pJMmNdBh9kmm3DxHf6AkK47a
|
||||
43gO/dRWiWo2rZ/+Jw7uyqOb23U0MydP7kia0p3tzCUBPsrlgnichYG5RNFp0wqy
|
||||
3VT1TYECgYEA0Y9vENy1jJd+s7WbGrsRtSKxfZgtJr0yjSlQVYrIlwbZSGn+ndxq
|
||||
V2vVlwIgLX3pz6T40BMfk6SNx08jjy0Sgn6OAM0ILrinno8yWcSAMCmfCU0S/3O1
|
||||
55bqtcnk4XTHBHzJ5OrnrPaW5ourvJz0lcWEKMg3BXxLzaF6ZRy85nECgYEAwPMD
|
||||
LNAKLCDrUMyYFOpPyPLe7wvszcFvPipGgerSgFP1c6N7xaMUdHDYqBfuis1khPGF
|
||||
YcMHeNBYmzX6yEGbp3lrB4PHpUySmTU3mv3u9I05aahInK21gXum3uRkCWyyIF6V
|
||||
T/qeszl9mVOCp0CC4eG3IMVpaD0UKDEHVhERYCkCgYAjuTPRyA4a3Wh38ilysRkf
|
||||
q75eDqcDx5Tqg3RyYKo5NK2troP9HSnzpSpQB8i8eI53G0RfFCN5479XjqIdMi3J
|
||||
mRFUCZ+vd0L7wKVwsBK6Ix49U6o9adhElnGEc9pUpLeYiD1SjMjZr1+iBYVNLeRz
|
||||
86vH1/mpMbsqXrCis/dvwQKBgGttomHr/w3s0jftget7PirrFrbP0+wHfDGHhjRF
|
||||
kyhCFtJovrwefYALaIXGtVjw3LusYZA570oT7pGUb2naJZkMYEwR0jG1vZWx7KDO
|
||||
K6JbkxDB0pPxn7JVL2bAkPYyX8boAohCSOQO6WBZ/8+xem3bp4OGhpa0EyoBik0g
|
||||
OaVpAoGATj4SyYsE10hGT676iie8zy3fi5IPC3E+x4QlVuusaLtuY8LJA50stjtx
|
||||
gUa/JAKlZZL+gvzvOviQIxyfIChXOdTt5uiOYkdHJDbAF3NSrji7hrXq4v8UZv75
|
||||
8hBrwJZIpy6y01dRlrriHmPRtEq1pk7JX2uUg0sP5g4BEcsaCbc=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAtR/wgDqWB4Maho5V6TjcL/NbNfjgIh7GcgkrB5RZcVT1GTej
|
||||
JlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6S8SpeJ1ofp5rBEoD/TIkvU0JOcid
|
||||
65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRyBIQzB0SIxSpnrsigqNsE1E94toDM
|
||||
x4wovjHu/9ABAImREV7Sz83OeFF00/sghrjTEJOD/gHf04JCn9MgNOqvSTysr9LX
|
||||
Wg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5yD41mi+hT8Rh+W8Je8rsiML4VMxz
|
||||
sb1l9303asw6suo5bLTISKNSbu1nt1NkpNxzywIDAQABAoIBAQCQkbvPPfP+bwC/
|
||||
IeEk1IO7qkzFWa7czR+safD0jc6OjTdNN4F716Q6yt4zEzLKu8VliiW+C23EBQiD
|
||||
7asKf4DvdTun0ExVtHDK7aEdeealSlXwz1ZtdypyILbtq1UGo/rR0v4x601rQPl0
|
||||
IrBmFf6D6FkqleNtLJmxguXpoVfLdYKNwkxH2ux+GOA9r2o5pUCQmJGDap5YWRuQ
|
||||
uB71ewJjVWujaL3e1ac/5cP7/tqWmgAiOaN8sYdD6+oWOR47bHj8JKcMBSl4y2QC
|
||||
dL31cGmmf5KqBbtISki3RXfHHjT7E3Z85CbESkKTZlEb1ar3XmepY6Z7V5UO16oz
|
||||
fFE5R6khAoGBAOl9Qb+qYVVO5ugE65ORjYVeuXykANhM9ssiY5a6zuAakWzw7Zv3
|
||||
k6PXm9p7azlEXAlTnTXVwHYMyuuzZDvQ8LRV1iBOdPuIkUAmaQ5K9ASD7VcoHexh
|
||||
k8DAKf9Ln7sTRaMdvgceRNczOmJOBIEpTZkssA/jVGXZsoyTWYl1en/ZAoGBAMaW
|
||||
RnNbSNprEV2b8UeAJ6i77c4SXwu1I8X2NLtiLScb1ETBjfrdHmdlJglfyd/0gmhH
|
||||
p/43Ku2iGUoY5KtuOI6QmahrJYQscRQhoj252VXadG6fNWWAlpgdCm9houhHb5BF
|
||||
3zge/bTr0anUe9EA7Z/ymav12rEouoNjIlhI9C5DAoGATR85a2SMt8/TB0owwdJu
|
||||
62GpZNkLCmcJkXkvaecUVAOSi2hdI4o4MwMRkK35cbX5rH74y4JqCtQY5pefgP53
|
||||
sykzDAK+MyMdzxGg2764MRGegI5Yq+5jDmSquo+xF+q6srEtRk6iMG7UVwosBLmu
|
||||
zuxqzySoiOfKSRKWnYe3SakCgYEAwWMkVkAmETXE4oDzFSsS8/mW2l//mPocTTK3
|
||||
JWe1CunJ6+8FYbAlZJEW2ngismp8+CoXybNVpbZ+pC7buKoMf6EHUgCNt0pEEFO0
|
||||
mCG9KSMk0XlPWXpArP9S4yaUq1itpzSz7QYZES+4rIcU0HLz9RgeWFyCTJWaFErc
|
||||
7laVG9sCgYBKOtk5WlIOP4BxSd2y4cYzohgwTZIs1/2kTEn1u4eH73M1xvAlHHFB
|
||||
wSF5QXgDKJ8pPAOhNWpdLO/PdtnQn91nOvTNc+ShJZzjdbneUdQVpWpoBf72uA+N
|
||||
6rIVf1JBUL2p7HFHaGdUZC7KGQ+yv6ZHrE1+7202nuDvJdvGEEdFsQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnfKBDG/K0TnGT7Xu8q1N
|
||||
45sNWvIK91SqNg8nvN2uVeKoHADTcsus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9r
|
||||
yfSNDhWDWloNkpGEeWif2BnHUu46Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnV
|
||||
DNfSEASVIppEBYjDX203ypmURIzU6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+t
|
||||
BlcnMrkv/40DSUkehQIl2JmlFrl2Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5N
|
||||
Md0KFa6CwZUUSHJqH5GFy5Y2yl4lg8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxI
|
||||
GQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtR/wgDqWB4Maho5V6Tjc
|
||||
L/NbNfjgIh7GcgkrB5RZcVT1GTejJlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6
|
||||
S8SpeJ1ofp5rBEoD/TIkvU0JOcid65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRy
|
||||
BIQzB0SIxSpnrsigqNsE1E94toDMx4wovjHu/9ABAImREV7Sz83OeFF00/sghrjT
|
||||
EJOD/gHf04JCn9MgNOqvSTysr9LXWg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5
|
||||
yD41mi+hT8Rh+W8Je8rsiML4VMxzsb1l9303asw6suo5bLTISKNSbu1nt1NkpNxz
|
||||
ywIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlSPMetaDataXML => {
|
||||
"proxy.com" => {
|
||||
samlSPMetaDataXML =>
|
||||
samlSPMetaDataXML( 'proxy', 'HTTP-POST' )
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub proxy {
|
||||
return LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
domain => 'proxy.com',
|
||||
portal => 'http://auth.proxy.com',
|
||||
authentication => 'SAML',
|
||||
userDB => 'Same',
|
||||
issuerDBCASActivation => 1,
|
||||
casAttr => 'uid',
|
||||
casAttributes => { cn => 'cn', uid => 'uid', mail => 'mail', },
|
||||
casAccessControlPolicy => 'none',
|
||||
multiValuesSeparator => ';',
|
||||
samlDiscoveryProtocolURL => 'http://discovery.example.com/',
|
||||
samlDiscoveryProtocolActivation => 1,
|
||||
samlIDPMetaDataExportedAttributes => {
|
||||
idp => {
|
||||
mail => "0;mail;;",
|
||||
uid => "1;uid",
|
||||
cn => "0;cn"
|
||||
},
|
||||
idp2 => {
|
||||
mail => "0;mail;;",
|
||||
uid => "1;uid",
|
||||
cn => "0;cn"
|
||||
}
|
||||
},
|
||||
samlIDPMetaDataOptions => {
|
||||
idp => {
|
||||
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
||||
samlIDPMetaDataOptionsSSOBinding => 'post',
|
||||
samlIDPMetaDataOptionsSLOBinding => 'post',
|
||||
samlIDPMetaDataOptionsSignSSOMessage => 1,
|
||||
samlIDPMetaDataOptionsSignSLOMessage => 1,
|
||||
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsForceUTF8 => 1,
|
||||
},
|
||||
idp2 => {
|
||||
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
||||
samlIDPMetaDataOptionsSSOBinding => 'post',
|
||||
samlIDPMetaDataOptionsSLOBinding => 'post',
|
||||
samlIDPMetaDataOptionsSignSSOMessage => 1,
|
||||
samlIDPMetaDataOptionsSignSLOMessage => 1,
|
||||
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsForceUTF8 => 1,
|
||||
}
|
||||
},
|
||||
samlIDPMetaDataExportedAttributes => {
|
||||
idp => {
|
||||
"uid" => "0;uid;;",
|
||||
"cn" => "1;cn;;",
|
||||
},
|
||||
idp2 => {
|
||||
"uid" => "0;uid;;",
|
||||
"cn" => "1;cn;;",
|
||||
},
|
||||
},
|
||||
samlIDPMetaDataXML => {
|
||||
idp => {
|
||||
samlIDPMetaDataXML =>
|
||||
samlIDPMetaDataXML( 'idp', 'HTTP-POST' )
|
||||
},
|
||||
idp2 => {
|
||||
samlIDPMetaDataXML =>
|
||||
samlIDPMetaDataXML( 'idp2', 'HTTP-POST' )
|
||||
}
|
||||
},
|
||||
samlOrganizationDisplayName => "SP",
|
||||
samlOrganizationName => "SP",
|
||||
samlOrganizationURL => "http://www.proxy.com",
|
||||
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4iToYAEmWQxgZDihGVz
|
||||
MMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKR
|
||||
FXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJ
|
||||
GZNX7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTja
|
||||
Sxsp4UndTI8/+mGSRSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAq
|
||||
Cq8odmbI0yCRZiTL9ybKWRKqWJoKJ0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9N
|
||||
qwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAsRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiG
|
||||
e/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIl
|
||||
l0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVLR+QUm+/1LIKYb3OCBTvOlY7x
|
||||
HoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8rUWRZbbDn31Tm
|
||||
Kjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
|
||||
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+wIDAQABAoIBAEkZrk8iiJKJ0WAx
|
||||
IrsyKNbXuWKLTYgnxcRCyzKofrfID+YcU39j8JeI0fKbajQUZ7qhnlTLwtU//+2h
|
||||
SqzyVu6/add/v7ZRWQw3L7cGzKK2THHzKVtLk/t7N3QroDdf1LMrQvkFP2HmcWS0
|
||||
/yN62hXtXHb/qpY4Nn+6JQyUpM5dkv8S/QjDl2NTdyWrXKzWp+4I3QLQ20f4zym+
|
||||
ir7RennziMc0HlQNcTjGAUbFULtdqEfSFWhNK7UjiRY+S0XV2xJIbGjnxUQH62fS
|
||||
w1ZzYsF7sBtoSckvfL4WfGbylhOVnliU05RLU2c67PRjj1Gskoslq1Ow/3DHR7rI
|
||||
BSBpV8ECgYEA1eHfcog7xQGDkW+cshJtFPFx+9MegB58gFW1rl0rn+tfbexvoSEA
|
||||
7G7EOTyaU6OAI+8StiRT6AYTgEU7PMM9zDykdGIWj3h0OpHGA86xhEiiaaM2DDRv
|
||||
/DEKRVlEdmRLLLY28pJVHOMYomia3mb2VKZGg2VfGtSfjg1GXD3I8OECgYEA0/X0
|
||||
U55KjZ1JQTPUgFc1WK1NxX9MaH+NcpDaolEUy3Qf3QTbfws+a9K3vwCn7EpQhrfs
|
||||
I6RVUtwFdCyfl/jzBY9Gykkg03sMgW7Qw2SCCsSt05M+jDtBbNJ7esP6PAeKFvXZ
|
||||
ZWhdeiAa4kM/P6gtvZXQ4tY4LkSbcd6b0SzzFFsCgYBjMsusFzuBd95JyfZnMNye
|
||||
5gzzu0teKMWd0CLfqB7foQ81sH9lwCTpg8ZGtbDuMdrwz6ViDR9NceQBjhqXaAZ1
|
||||
f3rW79d+22Ms9wdcJLV4oSeSzzv2FSwLT8NvvqNeNc4YArshbnVDXKDEUrfhhueh
|
||||
Ay2ZK58clpkaDVYg2hckgQKBgG3KuhtSI/YE4fwXN9yez7A2XNGPZem/IGqWo9lu
|
||||
PGJCrXqT2IqPLW82gB083r6jo+CUhonTxqqb82tA7g4PUvqvQ5Dmnk1NMKYe255K
|
||||
gp3HUO8GF2EWFIak5Hcr6oOLuDi6cjh3/euTk7ld8fYsTD0mzEOjiQhWW1p5X6bT
|
||||
LLp/AoGAHvkxA1NM1HJ3myAREbwNXxRy/nhNt4mwMkZ6hPQsW/Eg/3r7j6MJOFrm
|
||||
U8AJJjDGKe6nlXhhnMoQfJzAc0cYNgjktmJXW27fHGIwt/2QwYNFHPK3s7HTrfH6
|
||||
7T4XKT3yGeeeyC2soKJQPlGB+ETdIUnXa7eo9KVWtMTgISyx1Qk=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAu4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh
|
||||
5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsC
|
||||
uDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX7bglfEc9+QQpYTqN1rkdN1PV
|
||||
U0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGSRSq+nrT2zyQR
|
||||
M/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
|
||||
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9NqwIDAQABAoIBABE0Cjb6g3F+23vD
|
||||
SsRSeiqzrFrfOEqtXK+VGrfWzHS7V7Ozg6eW/H+HGJXUzUuQcklfg7EFA3JB41a0
|
||||
GxW3oA+UElkfCV/dcAG5NbRqGQKScEz9glZb5FikgDLqiPP+HabS/gvQSu71t2HI
|
||||
3KxSRJdwCNTp26Z28pxxYUpmELTtxd9vlHjffit2Mnt2uc8hOtFHdNavfYwvYH7o
|
||||
bmlckp7b/JVOy2Yy21O94ZWkE498jXyn71Gr+V1cnJ0RrmYbhQqIvFpFHj98Pf4O
|
||||
if3c4YmBcZ4t7PUsZUYF3ooWt8k/mdigQC3D6p80OKe+wUTYKcCN0ZdFbiURv9pg
|
||||
CsqLh+ECgYEA9vA+9QfzvXC7S5yXgTkuRiusPlNye/AiyA/0oGjmjFZ1YNsT7awH
|
||||
6BjW6WE+rS4elKJu1GaefM/cDguH4ZmJc+eKgi4LDCqYw9rr9les3aneBc8demd3
|
||||
O/Ej1Pud1QxXArBNfBYo08vEqwST9P89clJC5090U6bGK2E0rTVu1w0CgYEAwmpG
|
||||
9LbOFeGCPmwX7Avuk7tQQfRSV6q9TFZo+HxDfKYvxec846l1vBenY2rrgYhtolYJ
|
||||
YS795LYgbSWRxGfgr1GuIbP5GsjHy6/1o6bS8M++GJ7KHArb0QLAYyQweqqb164A
|
||||
NvHJkveueWnxzeOlD9j2fcjEnBHwTnqjG+17CZcCgYEAqMXawa4FsNxzpmIISpHC
|
||||
RsNindZ60Kp3mzUMhPYtXI1a/C+/lxmU7dTMTgXgyIxU6lF6XkEk4TlPtWm8HTzK
|
||||
7SS7Te4aLt6OOo5N57hUtct7q4y7IQXGQHm3e8HdRdeBQJ0u2Dhs/xSt/hTK6w/n
|
||||
91Kx11Y+s02w88UkM53pe6ECgYAF/UYwVc1liSv9BlF6WSfBb1zam09KGh1405Sq
|
||||
SxG9LlV8cFJE5TyWTdg/TNTyiaRvAt2JG+yAdkfrdOPXvCeE3yxRJ30+IP9evA4C
|
||||
O6p19sBxe7rYQFFjUAVjSIMh1E22yEqDZtGB8JV0chob8K5uHY4CdAPylu7jTA3o
|
||||
V1maAwKBgQCSGQ3yzsk4EGN2xd/JdgGDzhKyTZTQKMWYqQcsYxRAQ7Paj7u+Wkgv
|
||||
dBeKcI0HwgpLy5ZohSd2erqieIsW0pEbJWCmos4IcO8tgNfEOa5WXYdyLbj5tFwt
|
||||
ctu4/BJdijqfpMAtG8pv6k09gYjfASVytXmydGcs/0rVKYCRQA8Tow==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRaod2RZ8hMFBl+Vhsnh
|
||||
yPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpi
|
||||
jpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6
|
||||
jLVLR+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1
|
||||
zO0njuqGHkwEpy8rUWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtY
|
||||
XVhuG8OrWQDoS5gYHSjdw1CTJyixeJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz
|
||||
+wIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlSPSSODescriptorAuthnRequestsSigned => 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub app {
|
||||
my ( $jwks, $metadata ) = @_;
|
||||
return LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
domain => 'app.com',
|
||||
portal => 'http://auth.app.com',
|
||||
authentication => 'CAS',
|
||||
userDB => 'Same',
|
||||
multiValuesSeparator => ';',
|
||||
casSrvMetaDataExportedVars => {
|
||||
proxy => {
|
||||
cn => 'cn',
|
||||
mail => 'mail',
|
||||
uid => 'uid',
|
||||
}
|
||||
},
|
||||
casSrvMetaDataOptions => {
|
||||
proxy => {
|
||||
casSrvMetaDataOptionsUrl => 'http://auth.proxy.com/cas',
|
||||
casSrvMetaDataOptionsGateway => 0,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,701 @@
|
|||
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 = 19;
|
||||
my $debug = 'error';
|
||||
my ( $idp, $sp, $rp, $res );
|
||||
my %handlerOR = ( idp => [], sp => [], rp => [] );
|
||||
|
||||
LWP::Protocol::PSGI->register(
|
||||
sub {
|
||||
my $req = Plack::Request->new(@_);
|
||||
ok( $req->uri =~ m#http://auth.(rp|sp).com(.*)#, ' REST request' );
|
||||
my $host = $1;
|
||||
my $url = $2;
|
||||
my ( $res, $client );
|
||||
count(1);
|
||||
if ( $host eq 'sp' ) {
|
||||
pass(" Request from RP to OP(sp), endpoint $url");
|
||||
$client = $sp;
|
||||
}
|
||||
elsif ( $host eq 'rp' ) {
|
||||
pass(' Request from OP to RP(proxy)');
|
||||
$client = $rp;
|
||||
}
|
||||
else {
|
||||
fail(' Aborting REST request (external)');
|
||||
return HTTP::Response->new(500);
|
||||
}
|
||||
if ( $req->method =~ /^post$/i ) {
|
||||
my $s = $req->content;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
$url, IO::String->new($s),
|
||||
length => length($s),
|
||||
type => $req->header('Content-Type'),
|
||||
),
|
||||
' Execute request'
|
||||
);
|
||||
}
|
||||
else {
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
$url,
|
||||
custom => {
|
||||
HTTP_AUTHORIZATION => $req->header('Authorization'),
|
||||
}
|
||||
),
|
||||
' Execute request'
|
||||
);
|
||||
}
|
||||
ok( $res->[0] == 200, ' Response is 200' );
|
||||
ok( getHeader( $res, 'Content-Type' ) =~ m#^application/json#,
|
||||
' Content is JSON' )
|
||||
or explain( $res->[1], 'Content-Type => application/json' );
|
||||
count(4);
|
||||
return $res;
|
||||
}
|
||||
);
|
||||
|
||||
SKIP: {
|
||||
eval "use Lasso";
|
||||
if ($@) {
|
||||
skip 'Lasso not found', $maintests;
|
||||
}
|
||||
|
||||
# Initialization
|
||||
switch ('idp');
|
||||
ok( $idp = idp(), 'IdP portal' );
|
||||
$handlerOR{idp} = \@Lemonldap::NG::Handler::Main::_onReload;
|
||||
|
||||
switch ('sp');
|
||||
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
|
||||
ok( $sp = sp(), 'Proxy portal' );
|
||||
$handlerOR{sp} = \@Lemonldap::NG::Handler::Main::_onReload;
|
||||
|
||||
ok(
|
||||
$res = $sp->_get('/oauth2/jwks'),
|
||||
'Get JWKS, endpoint /oauth2/jwks'
|
||||
);
|
||||
expectOK($res);
|
||||
my $jwks = $res->[2]->[0];
|
||||
|
||||
ok(
|
||||
$res = $sp->_get('/.well-known/openid-configuration'),
|
||||
'Get metadata, endpoint /.well-known/openid-configuration'
|
||||
);
|
||||
expectOK($res);
|
||||
my $metadata = $res->[2]->[0];
|
||||
|
||||
switch ('rp');
|
||||
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
|
||||
ok( $rp = rp( $jwks, $metadata ), 'RP portal' );
|
||||
$handlerOR{rp} = \@Lemonldap::NG::Handler::Main::_onReload;
|
||||
|
||||
# Query RP for auth
|
||||
ok( $res = $rp->_get( '/', accept => 'text/html' ), 'Unauth SP request' );
|
||||
my ( $url, $query ) =
|
||||
expectRedirection( $res,
|
||||
qr#http://auth.sp.com(/oauth2/authorize)\?(.*)$# );
|
||||
|
||||
# Push request to Proxy
|
||||
switch ('sp');
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
$url,
|
||||
query => $query,
|
||||
accept => 'text/html',
|
||||
|
||||
# cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata'
|
||||
),
|
||||
"Push request to OP, endpoint $url"
|
||||
);
|
||||
my $spPdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
|
||||
|
||||
|
||||
|
||||
my ( $url, $query ) =
|
||||
expectRedirection( $res, qr#^http://discovery.example.com/# );
|
||||
|
||||
# Return from WAYF
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
"/",
|
||||
query => "idp=".uri_escape("http://auth.idp.com/saml/metadata"),
|
||||
accept => 'text/html',
|
||||
cookie => $spPdata,
|
||||
),
|
||||
"Return from WAYF"
|
||||
);
|
||||
|
||||
$spPdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
|
||||
|
||||
|
||||
|
||||
|
||||
my ( $host, $tmp );
|
||||
( $url, $query ) = expectRedirection( $res,
|
||||
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
|
||||
|
||||
# Push SAML request to IdP
|
||||
switch ('idp');
|
||||
ok(
|
||||
$res = $idp->_get(
|
||||
$url,
|
||||
query => $query,
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Launch SAML request to IdP'
|
||||
);
|
||||
my $idpPdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
|
||||
|
||||
# Try to authenticate to IdP
|
||||
my $body = $res->[2]->[0];
|
||||
$body =~ s/^.*?<form.*?>//s;
|
||||
$body =~ s#</form>.*$##s;
|
||||
my %fields =
|
||||
( $body =~ /<input type="hidden".+?name="(.+?)".+?value="(.*?)"/sg );
|
||||
$fields{user} = $fields{password} = 'french';
|
||||
use URI::Escape;
|
||||
$query =
|
||||
join( '&', map { "$_=" . uri_escape( $fields{$_} ) } keys %fields );
|
||||
ok(
|
||||
$res = $idp->_post(
|
||||
$url,
|
||||
IO::String->new($query),
|
||||
accept => 'text/html',
|
||||
length => length($query),
|
||||
cookie => $idpPdata,
|
||||
),
|
||||
'Post authentication'
|
||||
);
|
||||
|
||||
( $host, $url, $query ) = expectAutoPost( $res, 'auth.sp.com' );
|
||||
$query =~ s/\+/%2B/g;
|
||||
my $idpId = expectCookie($res);
|
||||
|
||||
# Post SAML response
|
||||
switch ('sp');
|
||||
ok(
|
||||
$res = $sp->_post(
|
||||
$url, IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
cookie => "lemonldapidp=http://auth.idp.com/saml/metadata;$spPdata"
|
||||
),
|
||||
'POST SAML response'
|
||||
);
|
||||
my $spId = expectCookie($res);
|
||||
( $url, $query ) = expectRedirection( $res,
|
||||
qr#http://auth.sp.com/*(/oauth2[^\?]*)(?:\?(.*))?$# );
|
||||
|
||||
# Follow internal redirection
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
$url,
|
||||
query => $query,
|
||||
accept => 'text/html',
|
||||
cookie =>
|
||||
"lemonldap=$spId;lemonldapidp=http://auth.idp.com/saml/metadata;$spPdata"
|
||||
),
|
||||
'Follow internal redirection from SAML-SP to OIDC-OP'
|
||||
);
|
||||
( $host, $tmp, $query ) = expectForm( $res, '#', undef, 'confirm' );
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
$url,
|
||||
query => $query,
|
||||
accept => 'text/html',
|
||||
cookie =>
|
||||
"lemonldap=$spId;lemonldapidp=http://auth.idp.com/saml/metadata;$spPdata"
|
||||
),
|
||||
'Confirm OIDC sharing'
|
||||
);
|
||||
($query) = expectRedirection( $res, qr#http://auth.rp.com/*\?(.*)$# );
|
||||
|
||||
# Follow redirection to RP
|
||||
switch ('rp');
|
||||
ok( $res = $rp->_get( '/', query => $query, accept => 'text/html' ),
|
||||
'Follow redirection to RP' );
|
||||
my $rpId = expectCookie($res);
|
||||
|
||||
# Logout initiated by RP
|
||||
ok(
|
||||
$res = $rp->_get(
|
||||
'/',
|
||||
query => 'logout',
|
||||
cookie => "lemonldap=$rpId",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Query RP for logout'
|
||||
);
|
||||
( $url, $query ) = expectRedirection( $res,
|
||||
qr#http://auth.sp.com(/oauth2/logout)\?(post_logout_redirect_uri=.+)$#
|
||||
);
|
||||
|
||||
# Push logout request to proxy
|
||||
switch ('sp');
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
$url,
|
||||
query => $query,
|
||||
cookie => "lemonldap=$spId",
|
||||
accept => 'text/html'
|
||||
),
|
||||
"Push logout request to OP/SP, endpoint $url"
|
||||
);
|
||||
( $host, $tmp, $query ) = expectForm( $res, '#', undef, 'confirm' );
|
||||
ok(
|
||||
$res = $sp->_post(
|
||||
$url, IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
cookie => "lemonldap=$spId",
|
||||
),
|
||||
"Confirm logout, endpoint $url"
|
||||
);
|
||||
( $url, $query ) = expectRedirection( $res,
|
||||
qr#http://auth.idp.com/*(/saml/singleLogout)\?(.*)# );
|
||||
|
||||
# Push logout to SAML IdP
|
||||
switch ('idp');
|
||||
ok(
|
||||
$res = $idp->_get(
|
||||
$url,
|
||||
query => $query,
|
||||
cookie => "lemonldap=$idpId",
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Push logout to SAML IdP'
|
||||
);
|
||||
( $url, $query ) = expectRedirection( $res,
|
||||
qr#http://auth.sp.com/*(/saml/proxySingleLogoutReturn)\?(.*)$# );
|
||||
|
||||
# Push logout to SAML SP
|
||||
switch ('sp');
|
||||
ok(
|
||||
$res = $sp->_get(
|
||||
$url,
|
||||
query => $query,
|
||||
cookie => "lemonldap=$spId",
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Push logout to SAML IdP'
|
||||
);
|
||||
|
||||
#print STDERR Dumper($res);
|
||||
}
|
||||
|
||||
count($maintests);
|
||||
clean_sessions();
|
||||
done_testing( count() );
|
||||
|
||||
sub switch {
|
||||
my $type = shift;
|
||||
pass( '==> Switching to ' . uc($type) . ' <==' );
|
||||
count(1);
|
||||
@Lemonldap::NG::Handler::Main::_onReload = @{
|
||||
$handlerOR{$type};
|
||||
};
|
||||
}
|
||||
|
||||
sub idp {
|
||||
return LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
domain => 'idp.com',
|
||||
portal => 'http://auth.idp.com',
|
||||
authentication => 'Demo',
|
||||
userDB => 'Same',
|
||||
issuerDBSAMLActivation => 1,
|
||||
samlSPMetaDataOptions => {
|
||||
'sp.com' => {
|
||||
samlSPMetaDataOptionsEncryptionMode => 'none',
|
||||
samlSPMetaDataOptionsSignSSOMessage => 1,
|
||||
samlSPMetaDataOptionsSignSLOMessage => 1,
|
||||
samlSPMetaDataOptionsCheckSSOMessageSignature => 1,
|
||||
samlSPMetaDataOptionsCheckSLOMessageSignature => 1,
|
||||
}
|
||||
},
|
||||
samlSPMetaDataExportedAttributes => {
|
||||
'sp.com' => {
|
||||
cn =>
|
||||
'1;cn;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
|
||||
uid =>
|
||||
'1;uid;urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
|
||||
}
|
||||
},
|
||||
samlOrganizationDisplayName => "IDP",
|
||||
samlOrganizationName => "IDP",
|
||||
samlOrganizationURL => "http://www.idp.com/",
|
||||
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAnfKBDG/K0TnGT7Xu8q1N45sNWvIK91SqNg8nvN2uVeKoHADT
|
||||
csus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9ryfSNDhWDWloNkpGEeWif2BnHUu46
|
||||
Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnVDNfSEASVIppEBYjDX203ypmURIzU
|
||||
6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+tBlcnMrkv/40DSUkehQIl2JmlFrl2
|
||||
Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5NMd0KFa6CwZUUSHJqH5GFy5Y2yl4l
|
||||
g8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxIGQIDAQABAoIBAHnfqjX3eO8SfnP5
|
||||
NURp90Td2mNHirCn0qLd9NKl1ySMPR1GgeH9SQ7Umu32EcteAUL5dOw2PiTZVmeW
|
||||
cKINgsWVftXUQcOQ4xIqWKb51QUBdy0FhxrZRSFjWxXt5iYK1PmzHfsax/g1/S9C
|
||||
RnqtFyjOy1bywkSt9jiy+9YBR2B7BDhLHlILbijWn5zaecaV4YA+L1UK4M/mehdb
|
||||
+0FVPavbGpnlqBRTY+7YXfZ/mRPCfn5DvO9lW1O0pJMmNdBh9kmm3DxHf6AkK47a
|
||||
43gO/dRWiWo2rZ/+Jw7uyqOb23U0MydP7kia0p3tzCUBPsrlgnichYG5RNFp0wqy
|
||||
3VT1TYECgYEA0Y9vENy1jJd+s7WbGrsRtSKxfZgtJr0yjSlQVYrIlwbZSGn+ndxq
|
||||
V2vVlwIgLX3pz6T40BMfk6SNx08jjy0Sgn6OAM0ILrinno8yWcSAMCmfCU0S/3O1
|
||||
55bqtcnk4XTHBHzJ5OrnrPaW5ourvJz0lcWEKMg3BXxLzaF6ZRy85nECgYEAwPMD
|
||||
LNAKLCDrUMyYFOpPyPLe7wvszcFvPipGgerSgFP1c6N7xaMUdHDYqBfuis1khPGF
|
||||
YcMHeNBYmzX6yEGbp3lrB4PHpUySmTU3mv3u9I05aahInK21gXum3uRkCWyyIF6V
|
||||
T/qeszl9mVOCp0CC4eG3IMVpaD0UKDEHVhERYCkCgYAjuTPRyA4a3Wh38ilysRkf
|
||||
q75eDqcDx5Tqg3RyYKo5NK2troP9HSnzpSpQB8i8eI53G0RfFCN5479XjqIdMi3J
|
||||
mRFUCZ+vd0L7wKVwsBK6Ix49U6o9adhElnGEc9pUpLeYiD1SjMjZr1+iBYVNLeRz
|
||||
86vH1/mpMbsqXrCis/dvwQKBgGttomHr/w3s0jftget7PirrFrbP0+wHfDGHhjRF
|
||||
kyhCFtJovrwefYALaIXGtVjw3LusYZA570oT7pGUb2naJZkMYEwR0jG1vZWx7KDO
|
||||
K6JbkxDB0pPxn7JVL2bAkPYyX8boAohCSOQO6WBZ/8+xem3bp4OGhpa0EyoBik0g
|
||||
OaVpAoGATj4SyYsE10hGT676iie8zy3fi5IPC3E+x4QlVuusaLtuY8LJA50stjtx
|
||||
gUa/JAKlZZL+gvzvOviQIxyfIChXOdTt5uiOYkdHJDbAF3NSrji7hrXq4v8UZv75
|
||||
8hBrwJZIpy6y01dRlrriHmPRtEq1pk7JX2uUg0sP5g4BEcsaCbc=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAtR/wgDqWB4Maho5V6TjcL/NbNfjgIh7GcgkrB5RZcVT1GTej
|
||||
JlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6S8SpeJ1ofp5rBEoD/TIkvU0JOcid
|
||||
65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRyBIQzB0SIxSpnrsigqNsE1E94toDM
|
||||
x4wovjHu/9ABAImREV7Sz83OeFF00/sghrjTEJOD/gHf04JCn9MgNOqvSTysr9LX
|
||||
Wg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5yD41mi+hT8Rh+W8Je8rsiML4VMxz
|
||||
sb1l9303asw6suo5bLTISKNSbu1nt1NkpNxzywIDAQABAoIBAQCQkbvPPfP+bwC/
|
||||
IeEk1IO7qkzFWa7czR+safD0jc6OjTdNN4F716Q6yt4zEzLKu8VliiW+C23EBQiD
|
||||
7asKf4DvdTun0ExVtHDK7aEdeealSlXwz1ZtdypyILbtq1UGo/rR0v4x601rQPl0
|
||||
IrBmFf6D6FkqleNtLJmxguXpoVfLdYKNwkxH2ux+GOA9r2o5pUCQmJGDap5YWRuQ
|
||||
uB71ewJjVWujaL3e1ac/5cP7/tqWmgAiOaN8sYdD6+oWOR47bHj8JKcMBSl4y2QC
|
||||
dL31cGmmf5KqBbtISki3RXfHHjT7E3Z85CbESkKTZlEb1ar3XmepY6Z7V5UO16oz
|
||||
fFE5R6khAoGBAOl9Qb+qYVVO5ugE65ORjYVeuXykANhM9ssiY5a6zuAakWzw7Zv3
|
||||
k6PXm9p7azlEXAlTnTXVwHYMyuuzZDvQ8LRV1iBOdPuIkUAmaQ5K9ASD7VcoHexh
|
||||
k8DAKf9Ln7sTRaMdvgceRNczOmJOBIEpTZkssA/jVGXZsoyTWYl1en/ZAoGBAMaW
|
||||
RnNbSNprEV2b8UeAJ6i77c4SXwu1I8X2NLtiLScb1ETBjfrdHmdlJglfyd/0gmhH
|
||||
p/43Ku2iGUoY5KtuOI6QmahrJYQscRQhoj252VXadG6fNWWAlpgdCm9houhHb5BF
|
||||
3zge/bTr0anUe9EA7Z/ymav12rEouoNjIlhI9C5DAoGATR85a2SMt8/TB0owwdJu
|
||||
62GpZNkLCmcJkXkvaecUVAOSi2hdI4o4MwMRkK35cbX5rH74y4JqCtQY5pefgP53
|
||||
sykzDAK+MyMdzxGg2764MRGegI5Yq+5jDmSquo+xF+q6srEtRk6iMG7UVwosBLmu
|
||||
zuxqzySoiOfKSRKWnYe3SakCgYEAwWMkVkAmETXE4oDzFSsS8/mW2l//mPocTTK3
|
||||
JWe1CunJ6+8FYbAlZJEW2ngismp8+CoXybNVpbZ+pC7buKoMf6EHUgCNt0pEEFO0
|
||||
mCG9KSMk0XlPWXpArP9S4yaUq1itpzSz7QYZES+4rIcU0HLz9RgeWFyCTJWaFErc
|
||||
7laVG9sCgYBKOtk5WlIOP4BxSd2y4cYzohgwTZIs1/2kTEn1u4eH73M1xvAlHHFB
|
||||
wSF5QXgDKJ8pPAOhNWpdLO/PdtnQn91nOvTNc+ShJZzjdbneUdQVpWpoBf72uA+N
|
||||
6rIVf1JBUL2p7HFHaGdUZC7KGQ+yv6ZHrE1+7202nuDvJdvGEEdFsQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnfKBDG/K0TnGT7Xu8q1N
|
||||
45sNWvIK91SqNg8nvN2uVeKoHADTcsus5Xn3id5+8Q9TuMFsW9kIEeXiaPKXQa9r
|
||||
yfSNDhWDWloNkpGEeWif2BnHUu46Abu1UBWb0mH6VwcG1PR4qHruLis1odjQ1qnV
|
||||
DNfSEASVIppEBYjDX203ypmURIzU6h53GRRRlf1BLWkbVn9ysmDeR57Xw5Rsx/+t
|
||||
BlcnMrkv/40DSUkehQIl2JmlFrl2Caik+gU4pd20apA/pNLjBZF0OmGoS08AIR5N
|
||||
Md0KFa6CwZUUSHJqH5GFy5Y2yl4lg8K0klAS9q7L7aXI+eFQZhkwidjpxXnHPyxI
|
||||
GQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtR/wgDqWB4Maho5V6Tjc
|
||||
L/NbNfjgIh7GcgkrB5RZcVT1GTejJlMjUQdgBKBuZXQN+7/29P6UcGq1kYalURq6
|
||||
S8SpeJ1ofp5rBEoD/TIkvU0JOcid65wp+fdzXGXsfiZvHraU74jSCgjP/wqfVGRy
|
||||
BIQzB0SIxSpnrsigqNsE1E94toDMx4wovjHu/9ABAImREV7Sz83OeFF00/sghrjT
|
||||
EJOD/gHf04JCn9MgNOqvSTysr9LXWg/oUKQDEYeTq9ux6pq/oqv1MxwONbSZPtN5
|
||||
yD41mi+hT8Rh+W8Je8rsiML4VMxzsb1l9303asw6suo5bLTISKNSbu1nt1NkpNxz
|
||||
ywIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlSPMetaDataXML => {
|
||||
"sp.com" => {
|
||||
samlSPMetaDataXML =>
|
||||
samlSPMetaDataXML( 'sp', 'HTTP-Redirect' )
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub sp {
|
||||
return LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
domain => 'sp.com',
|
||||
portal => 'http://auth.sp.com',
|
||||
authentication => 'SAML',
|
||||
userDB => 'Same',
|
||||
issuerDBSAMLActivation => 0,
|
||||
issuerDBOpenIDConnectActivation => 1,
|
||||
samlDiscoveryProtocolURL => 'http://discovery.example.com/',
|
||||
samlDiscoveryProtocolActivation => 1,
|
||||
|
||||
oidcRPMetaDataExportedVars => {
|
||||
rp => {
|
||||
email => "mail",
|
||||
family_name => "cn",
|
||||
name => "cn"
|
||||
}
|
||||
},
|
||||
oidcRPMetaDataOptionsExtraClaims => {
|
||||
rp => {
|
||||
email => 'email',
|
||||
},
|
||||
},
|
||||
oidcServiceMetaDataIssuer => "http://auth.sp.com",
|
||||
oidcServiceMetaDataCheckSessionURI => "checksession.html",
|
||||
oidcServiceMetaDataJWKSURI => "jwks",
|
||||
oidcServiceMetaDataEndSessionURI => "logout",
|
||||
oidcServiceMetaDataRegistrationURI => "register",
|
||||
oidcServiceMetaDataTokenURI => "token",
|
||||
oidcServiceMetaDataUserInfoURI => "userinfo",
|
||||
oidcServiceAllowHybridFlow => 1,
|
||||
oidcServiceAllowImplicitFlow => 1,
|
||||
oidcServiceAllowDynamicRegistration => 1,
|
||||
oidcServiceAllowAuthorizationCodeFlow => 1,
|
||||
oidcRPMetaDataOptions => {
|
||||
rp => {
|
||||
oidcRPMetaDataOptionsDisplayName => "RP",
|
||||
oidcRPMetaDataOptionsIDTokenExpiration => 3600,
|
||||
oidcRPMetaDataOptionsClientID => "rpid",
|
||||
oidcRPMetaDataOptionsIDTokenSignAlg => "HS512",
|
||||
oidcRPMetaDataOptionsBypassConsent => 0,
|
||||
oidcRPMetaDataOptionsClientSecret => "rpsecret",
|
||||
oidcRPMetaDataOptionsUserIDAttr => "",
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 3600
|
||||
}
|
||||
},
|
||||
oidcOPMetaDataOptions => {},
|
||||
oidcOPMetaDataJSON => {},
|
||||
oidcOPMetaDataJWKS => {},
|
||||
oidcServiceMetaDataAuthnContext => {
|
||||
'loa-4' => 4,
|
||||
'loa-1' => 1,
|
||||
'loa-5' => 5,
|
||||
'loa-2' => 2,
|
||||
'loa-3' => 3
|
||||
},
|
||||
oidcServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAs2jsmIoFuWzMkilJaA8//5/T30cnuzX9GImXUrFR2k9EKTMt
|
||||
GMHCdKlWOl3BV+BTAU9TLz7Jzd/iJ5GJ6B8TrH1PHFmHpy8/qE/S5OhinIpIi7eb
|
||||
ABqnoVcwDdCa8ugzq8k8SWxhRNXfVIlwz4NH1caJ8lmiERFj7IvNKqEhzAk0pyDr
|
||||
8hubveTC39xREujKlsqutpPAFPJ3f2ybVsdykX5rx0h5SslG3jVWYhZ/SOb2aIzO
|
||||
r0RMjhQmsYRwbpt3anjlBZ98aOzg7GAkbO8093X5VVk9vaPRg0zxJQ0Do0YLyzkR
|
||||
isSAIFb0tdKuDnjRGK6y/N2j6At2HjkxntbtGQIDAQABAoIBADYq6LxJd977LWy3
|
||||
0HT9nboFPIf+SM2qSEc/S5Po+6ipJBA4ZlZCMf7dHa6znet1TDpqA9iQ4YcqIHMH
|
||||
6xZNQ7hhgSAzG9TrXBHqP+djDlrrGWotvjuy0IfS9ixFnnLWjrtAH9afRWLuG+a/
|
||||
NHNC1M6DiiTE0TzL/lpt/zzut3CNmWzH+t19X6UsxUg95AzooEeewEYkv25eumWD
|
||||
mfQZfCtSlIw1sp/QwxeJa/6LJw7KcPZ1wXUm1BN0b9eiKt9Cmni1MS7elgpZlgGt
|
||||
xtfGTZtNLQ7bgDiM8MHzUfPBhbceNSIx2BeCuOCs/7eaqgpyYHBbAbuBQex2H61l
|
||||
Lcc3Tz0CgYEA4Kx/avpCPxnvsJ+nHVQm5d/WERuDxk4vH1DNuCYBvXTdVCGADf6a
|
||||
F5No1JcTH3nPTyPWazOyGdT9LcsEJicLyD8vCM6hBFstG4XjqcAuqG/9DRsElpHQ
|
||||
yi1zc5DNP7Vxmiz9wII0Mjy0abYKtxnXh9YK4a9g6wrcTpvShhIcIb8CgYEAzGzG
|
||||
lorVCfX9jXULIznnR/uuP5aSnTEsn0xJeqTlbW0RFWLdj8aIL1peirh1X89HroB9
|
||||
GeTNqEJXD+3CVL2cx+BRggMDUmEz4hR59meZCDGUyT5fex4LIsceb/ESUl2jo6Sw
|
||||
HXwWbN67rQ55N4oiOcOppsGxzOHkl5HdExKidycCgYEAr5Qev2tz+fw65LzfzHvH
|
||||
Kj4S/KuT/5V6He731cFd+sEpdmX3vPgLVAFPG1Q1DZQT/rTzDDQKK0XX1cGiLG63
|
||||
NnaqOye/jbfzOF8Z277kt51NFMDYhRLPKDD82IOA4xjY/rPKWndmcxwdob8yAIWh
|
||||
efY76sMz6ntCT+xWSZA9i+ECgYBWMZM2TIlxLsBfEbfFfZewOUWKWEGvd9l5vV/K
|
||||
D5cRIYivfMUw5yPq2267jPUolayCvniBH4E7beVpuPVUZ7KgcEvNxtlytbt7muil
|
||||
5Z6X3tf+VodJ0Swe2NhTmNEB26uwxzLe68BE3VFCsbSYn2y48HAq+MawPZr18bHG
|
||||
ZfgMxwKBgHHRg6HYqF5Pegzk1746uH2G+OoCovk5ylGGYzcH2ghWTK4agCHfBcDt
|
||||
EYqYAev/l82wi+OZ5O8U+qjFUpT1CVeUJdDs0o5u19v0UJjunU1cwh9jsxBZAWLy
|
||||
PAGd6SWf4S3uQCTw6dLeMna25YIlPh5qPA6I/pAahe8e3nSu2ckl
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
oidcServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs2jsmIoFuWzMkilJaA8/
|
||||
/5/T30cnuzX9GImXUrFR2k9EKTMtGMHCdKlWOl3BV+BTAU9TLz7Jzd/iJ5GJ6B8T
|
||||
rH1PHFmHpy8/qE/S5OhinIpIi7ebABqnoVcwDdCa8ugzq8k8SWxhRNXfVIlwz4NH
|
||||
1caJ8lmiERFj7IvNKqEhzAk0pyDr8hubveTC39xREujKlsqutpPAFPJ3f2ybVsdy
|
||||
kX5rx0h5SslG3jVWYhZ/SOb2aIzOr0RMjhQmsYRwbpt3anjlBZ98aOzg7GAkbO80
|
||||
93X5VVk9vaPRg0zxJQ0Do0YLyzkRisSAIFb0tdKuDnjRGK6y/N2j6At2Hjkxntbt
|
||||
GQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlIDPMetaDataExportedAttributes => {
|
||||
idp => {
|
||||
mail => "0;mail;;",
|
||||
uid => "1;uid",
|
||||
cn => "0;cn"
|
||||
},
|
||||
idp2 => {
|
||||
mail => "0;mail;;",
|
||||
uid => "1;uid",
|
||||
cn => "0;cn"
|
||||
}
|
||||
},
|
||||
samlIDPMetaDataOptions => {
|
||||
idp => {
|
||||
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
||||
samlIDPMetaDataOptionsSSOBinding => 'redirect',
|
||||
samlIDPMetaDataOptionsSLOBinding => 'redirect',
|
||||
samlIDPMetaDataOptionsSignSSOMessage => 1,
|
||||
samlIDPMetaDataOptionsSignSLOMessage => 1,
|
||||
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsForceUTF8 => 1,
|
||||
},
|
||||
idp2 => {
|
||||
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
||||
samlIDPMetaDataOptionsSSOBinding => 'redirect',
|
||||
samlIDPMetaDataOptionsSLOBinding => 'redirect',
|
||||
samlIDPMetaDataOptionsSignSSOMessage => 1,
|
||||
samlIDPMetaDataOptionsSignSLOMessage => 1,
|
||||
samlIDPMetaDataOptionsCheckSSOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsCheckSLOMessageSignature => 1,
|
||||
samlIDPMetaDataOptionsForceUTF8 => 1,
|
||||
}
|
||||
},
|
||||
samlIDPMetaDataExportedAttributes => {
|
||||
idp => {
|
||||
"uid" => "0;uid;;",
|
||||
"cn" => "1;cn;;",
|
||||
},
|
||||
idp2 => {
|
||||
"uid" => "0;uid;;",
|
||||
"cn" => "1;cn;;",
|
||||
},
|
||||
},
|
||||
samlIDPMetaDataXML => {
|
||||
idp => {
|
||||
samlIDPMetaDataXML =>
|
||||
samlIDPMetaDataXML( 'idp', 'HTTP-Redirect' )
|
||||
},
|
||||
idp2 => {
|
||||
samlIDPMetaDataXML =>
|
||||
samlIDPMetaDataXML( 'idp2', 'HTTP-Redirect' )
|
||||
}
|
||||
},
|
||||
samlOrganizationDisplayName => "SP",
|
||||
samlOrganizationName => "SP",
|
||||
samlOrganizationURL => "http://www.sp.com",
|
||||
samlServicePublicKeySig => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu4iToYAEmWQxgZDihGVz
|
||||
MMql1elPn37domWcvXeU2E4yt2hh5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKR
|
||||
FXd7BrOhQIDC0TZPRVB0XHarUtsCuDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJ
|
||||
GZNX7bglfEc9+QQpYTqN1rkdN1PVU0epNMokFFGho5pLRqLUV5+I/QXAL49jfTja
|
||||
Sxsp4UndTI8/+mGSRSq+nrT2zyQRM/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAq
|
||||
Cq8odmbI0yCRZiTL9ybKWRKqWJoKJ0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9N
|
||||
qwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlServicePrivateKeyEnc => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAsRaod2RZ8hMFBl+VhsnhyPM8l/Fj1obnBxfQIaWuHFIFfXiG
|
||||
e/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpijpcg0QgfBSEkfopKTgReYN8DiDIl
|
||||
l0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6jLVLR+QUm+/1LIKYb3OCBTvOlY7x
|
||||
HoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1zO0njuqGHkwEpy8rUWRZbbDn31Tm
|
||||
Kjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtYXVhuG8OrWQDoS5gYHSjdw1CTJyix
|
||||
eJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz+wIDAQABAoIBAEkZrk8iiJKJ0WAx
|
||||
IrsyKNbXuWKLTYgnxcRCyzKofrfID+YcU39j8JeI0fKbajQUZ7qhnlTLwtU//+2h
|
||||
SqzyVu6/add/v7ZRWQw3L7cGzKK2THHzKVtLk/t7N3QroDdf1LMrQvkFP2HmcWS0
|
||||
/yN62hXtXHb/qpY4Nn+6JQyUpM5dkv8S/QjDl2NTdyWrXKzWp+4I3QLQ20f4zym+
|
||||
ir7RennziMc0HlQNcTjGAUbFULtdqEfSFWhNK7UjiRY+S0XV2xJIbGjnxUQH62fS
|
||||
w1ZzYsF7sBtoSckvfL4WfGbylhOVnliU05RLU2c67PRjj1Gskoslq1Ow/3DHR7rI
|
||||
BSBpV8ECgYEA1eHfcog7xQGDkW+cshJtFPFx+9MegB58gFW1rl0rn+tfbexvoSEA
|
||||
7G7EOTyaU6OAI+8StiRT6AYTgEU7PMM9zDykdGIWj3h0OpHGA86xhEiiaaM2DDRv
|
||||
/DEKRVlEdmRLLLY28pJVHOMYomia3mb2VKZGg2VfGtSfjg1GXD3I8OECgYEA0/X0
|
||||
U55KjZ1JQTPUgFc1WK1NxX9MaH+NcpDaolEUy3Qf3QTbfws+a9K3vwCn7EpQhrfs
|
||||
I6RVUtwFdCyfl/jzBY9Gykkg03sMgW7Qw2SCCsSt05M+jDtBbNJ7esP6PAeKFvXZ
|
||||
ZWhdeiAa4kM/P6gtvZXQ4tY4LkSbcd6b0SzzFFsCgYBjMsusFzuBd95JyfZnMNye
|
||||
5gzzu0teKMWd0CLfqB7foQ81sH9lwCTpg8ZGtbDuMdrwz6ViDR9NceQBjhqXaAZ1
|
||||
f3rW79d+22Ms9wdcJLV4oSeSzzv2FSwLT8NvvqNeNc4YArshbnVDXKDEUrfhhueh
|
||||
Ay2ZK58clpkaDVYg2hckgQKBgG3KuhtSI/YE4fwXN9yez7A2XNGPZem/IGqWo9lu
|
||||
PGJCrXqT2IqPLW82gB083r6jo+CUhonTxqqb82tA7g4PUvqvQ5Dmnk1NMKYe255K
|
||||
gp3HUO8GF2EWFIak5Hcr6oOLuDi6cjh3/euTk7ld8fYsTD0mzEOjiQhWW1p5X6bT
|
||||
LLp/AoGAHvkxA1NM1HJ3myAREbwNXxRy/nhNt4mwMkZ6hPQsW/Eg/3r7j6MJOFrm
|
||||
U8AJJjDGKe6nlXhhnMoQfJzAc0cYNgjktmJXW27fHGIwt/2QwYNFHPK3s7HTrfH6
|
||||
7T4XKT3yGeeeyC2soKJQPlGB+ETdIUnXa7eo9KVWtMTgISyx1Qk=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePrivateKeySig => "-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAu4iToYAEmWQxgZDihGVzMMql1elPn37domWcvXeU2E4yt2hh
|
||||
5jkQHiFjgodfOlNeRIw5QJVlUBwr+CQvbaKRFXd7BrOhQIDC0TZPRVB0XHarUtsC
|
||||
uDekN4/2GKSzHsoToKUVPWq9thsuek3xkpsJGZNX7bglfEc9+QQpYTqN1rkdN1PV
|
||||
U0epNMokFFGho5pLRqLUV5+I/QXAL49jfTjaSxsp4UndTI8/+mGSRSq+nrT2zyQR
|
||||
M/vkj5vR9ZVz67HO/+Wk3Mx6RAwkVcMdgMAqCq8odmbI0yCRZiTL9ybKWRKqWJoK
|
||||
J0p5+Q2fPEBPupQZR09Jt/JPuLVSsGfCxi9NqwIDAQABAoIBABE0Cjb6g3F+23vD
|
||||
SsRSeiqzrFrfOEqtXK+VGrfWzHS7V7Ozg6eW/H+HGJXUzUuQcklfg7EFA3JB41a0
|
||||
GxW3oA+UElkfCV/dcAG5NbRqGQKScEz9glZb5FikgDLqiPP+HabS/gvQSu71t2HI
|
||||
3KxSRJdwCNTp26Z28pxxYUpmELTtxd9vlHjffit2Mnt2uc8hOtFHdNavfYwvYH7o
|
||||
bmlckp7b/JVOy2Yy21O94ZWkE498jXyn71Gr+V1cnJ0RrmYbhQqIvFpFHj98Pf4O
|
||||
if3c4YmBcZ4t7PUsZUYF3ooWt8k/mdigQC3D6p80OKe+wUTYKcCN0ZdFbiURv9pg
|
||||
CsqLh+ECgYEA9vA+9QfzvXC7S5yXgTkuRiusPlNye/AiyA/0oGjmjFZ1YNsT7awH
|
||||
6BjW6WE+rS4elKJu1GaefM/cDguH4ZmJc+eKgi4LDCqYw9rr9les3aneBc8demd3
|
||||
O/Ej1Pud1QxXArBNfBYo08vEqwST9P89clJC5090U6bGK2E0rTVu1w0CgYEAwmpG
|
||||
9LbOFeGCPmwX7Avuk7tQQfRSV6q9TFZo+HxDfKYvxec846l1vBenY2rrgYhtolYJ
|
||||
YS795LYgbSWRxGfgr1GuIbP5GsjHy6/1o6bS8M++GJ7KHArb0QLAYyQweqqb164A
|
||||
NvHJkveueWnxzeOlD9j2fcjEnBHwTnqjG+17CZcCgYEAqMXawa4FsNxzpmIISpHC
|
||||
RsNindZ60Kp3mzUMhPYtXI1a/C+/lxmU7dTMTgXgyIxU6lF6XkEk4TlPtWm8HTzK
|
||||
7SS7Te4aLt6OOo5N57hUtct7q4y7IQXGQHm3e8HdRdeBQJ0u2Dhs/xSt/hTK6w/n
|
||||
91Kx11Y+s02w88UkM53pe6ECgYAF/UYwVc1liSv9BlF6WSfBb1zam09KGh1405Sq
|
||||
SxG9LlV8cFJE5TyWTdg/TNTyiaRvAt2JG+yAdkfrdOPXvCeE3yxRJ30+IP9evA4C
|
||||
O6p19sBxe7rYQFFjUAVjSIMh1E22yEqDZtGB8JV0chob8K5uHY4CdAPylu7jTA3o
|
||||
V1maAwKBgQCSGQ3yzsk4EGN2xd/JdgGDzhKyTZTQKMWYqQcsYxRAQ7Paj7u+Wkgv
|
||||
dBeKcI0HwgpLy5ZohSd2erqieIsW0pEbJWCmos4IcO8tgNfEOa5WXYdyLbj5tFwt
|
||||
ctu4/BJdijqfpMAtG8pv6k09gYjfASVytXmydGcs/0rVKYCRQA8Tow==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
",
|
||||
samlServicePublicKeyEnc => "-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRaod2RZ8hMFBl+Vhsnh
|
||||
yPM8l/Fj1obnBxfQIaWuHFIFfXiGe/CYHuZ5QJQLnZxHMJX6LL3Sh+Usog3p0jpi
|
||||
jpcg0QgfBSEkfopKTgReYN8DiDIll0rV1XdTni7E85Nd1YyNy3ui/ZD+UShWwqu6
|
||||
jLVLR+QUm+/1LIKYb3OCBTvOlY7xHoP6NSU1+Mr+YzGBUacdO2vnNxe/PQhxIeP1
|
||||
zO0njuqGHkwEpy8rUWRZbbDn31TmKjqlhgtsz5HPhbRaYEExhyepKgBiNz+RyxtY
|
||||
XVhuG8OrWQDoS5gYHSjdw1CTJyixeJwyoqA9RGYguG5nh9zndi3LWAh7Z0lx+tIz
|
||||
+wIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
",
|
||||
samlSPSSODescriptorAuthnRequestsSigned => 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub rp {
|
||||
my ( $jwks, $metadata ) = @_;
|
||||
return LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
domain => 'rp.com',
|
||||
portal => 'http://auth.rp.com',
|
||||
authentication => 'OpenIDConnect',
|
||||
userDB => 'Same',
|
||||
oidcOPMetaDataExportedVars => {
|
||||
sp => {
|
||||
cn => "name",
|
||||
uid => "sub",
|
||||
sn => "family_name",
|
||||
mail => "email"
|
||||
}
|
||||
},
|
||||
oidcOPMetaDataOptions => {
|
||||
sp => {
|
||||
oidcOPMetaDataOptionsJWKSTimeout => 0,
|
||||
oidcOPMetaDataOptionsClientSecret => "rpsecret",
|
||||
oidcOPMetaDataOptionsScope => "openid profile email",
|
||||
oidcOPMetaDataOptionsStoreIDToken => 0,
|
||||
oidcOPMetaDataOptionsDisplay => "",
|
||||
oidcOPMetaDataOptionsClientID => "rpid",
|
||||
oidcOPMetaDataOptionsConfigurationURI =>
|
||||
"https://auth.sp.com/.well-known/openid-configuration"
|
||||
}
|
||||
},
|
||||
oidcOPMetaDataJWKS => {
|
||||
sp => $jwks,
|
||||
},
|
||||
oidcOPMetaDataJSON => {
|
||||
sp => $metadata,
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
|
@ -66,7 +66,7 @@ count(1);
|
|||
|
||||
# Expired token
|
||||
sleep 3;
|
||||
$query =~ s/user=dwho/user=rtyler/;
|
||||
$query =~ s/user=/user=rtyler/;
|
||||
$query =~ s/url=/url=http%3A%2F%2Ftest1.example.com/;
|
||||
|
||||
ok(
|
||||
|
@ -87,7 +87,7 @@ count(2);
|
|||
|
||||
# Valid token
|
||||
$query =~ s/user=/user=rtyler/;
|
||||
$query =~ s/url=/url=test1.example.com/;
|
||||
$query =~ s/url=/url=http%3A%2F%2Ftest1.example.com/;
|
||||
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
|
|
|
@ -18,6 +18,7 @@ my $client = LLNG::Manager::Test->new( {
|
|||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
checkUser => 1,
|
||||
requireToken => 0,
|
||||
checkUserIdRule => '$uid ne "msmith"',
|
||||
checkUserDisplayPersistentInfo => 1,
|
||||
checkUserDisplayEmptyValues => 1,
|
||||
}
|
||||
|
@ -28,7 +29,7 @@ my $client = LLNG::Manager::Test->new( {
|
|||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new('user=msmith&password=msmith'),
|
||||
IO::String->new('user=rtyler&password=rtyler'),
|
||||
length => 27,
|
||||
accept => 'text/html',
|
||||
),
|
||||
|
@ -73,6 +74,7 @@ expectRedirection( $res, 'http://auth.example.com/' );
|
|||
|
||||
# CheckUser form -> granted
|
||||
# ------------------------
|
||||
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/checkuser',
|
||||
|
@ -90,6 +92,14 @@ ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
|
|||
or explain( $res->[2]->[0], 'trspan="checkUser"' );
|
||||
count(1);
|
||||
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">_user</td>%,
|
||||
'Found attribute _user' )
|
||||
or explain( $res->[2]->[0], 'Attribute _user' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">dwho</td>%,
|
||||
'Found value dwho' )
|
||||
or explain( $res->[2]->[0], 'Value dwho' );
|
||||
count(2);
|
||||
|
||||
$query =~ s/user=dwho/user=rtyler/;
|
||||
$query =~ s/url=/url=http%3A%2F%2Ftry.example.com/;
|
||||
ok(
|
||||
|
@ -111,12 +121,7 @@ ok( $res->[2]->[0] =~ m%<span trspan="VHnotFound">%,
|
|||
or explain( $res->[2]->[0], 'trspan="VHnotFound"' );
|
||||
count(1);
|
||||
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, undef, '/checkuser', 'user', 'url' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
|
||||
or explain( $res->[2]->[0], 'trspan="checkUser"' );
|
||||
count(1);
|
||||
|
||||
# Request with good VH & user
|
||||
$query =~
|
||||
s/url=http%3A%2F%2Ftry.example.com/url=http%3A%2F%2Ftest1.example.com/;
|
||||
ok(
|
||||
|
@ -168,9 +173,8 @@ ok( $res->[2]->[0] =~ m%<td class="text-left">uid</td>%, 'Found uid' )
|
|||
or explain( $res->[2]->[0], 'Attribute Value uid' );
|
||||
count(11);
|
||||
|
||||
$query =~ s/user=dwho/user=msmith/;
|
||||
$query =~
|
||||
s/url=http%3A%2F%2Ftest1.example.com/url=http%3A%2F%2Fmanager.example.com%2Fmanager.html/;
|
||||
# Request a forbidden identity
|
||||
$query =~ s/user=rtyler/user=msmith/;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/checkuser',
|
||||
|
@ -183,9 +187,47 @@ ok(
|
|||
);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<div class="alert alert-danger"><b><span trspan="forbidden"></span></b></div>%,
|
||||
'Found trspan="forbidden"'
|
||||
) or explain( $res->[2]->[0], 'trspan="forbidden"' );
|
||||
m%<div class="message message-positive alert"><span trspan="PE5"></span></div>%,
|
||||
' PE5 found'
|
||||
) or explain( $res->[2]->[0], 'PE5 - Forbidden identity' );
|
||||
count(2);
|
||||
|
||||
# Request an unknown identity
|
||||
$query =~ s/user=msmith/user=davros/;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/checkuser',
|
||||
IO::String->new($query),
|
||||
cookie => "lemonldap=$id",
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'POST checkuser'
|
||||
);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<div class="message message-positive alert"><span trspan="PE5"></span></div>%,
|
||||
' PE5 found'
|
||||
) or explain( $res->[2]->[0], 'PE5 - Unknown identity' );
|
||||
count(2);
|
||||
|
||||
# Request an unvalid identity
|
||||
$query =~ s/user=dwho/user=%*'/;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/checkuser',
|
||||
IO::String->new($query),
|
||||
cookie => "lemonldap=$id",
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'POST checkuser'
|
||||
);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<div class="message message-positive alert"><span trspan="PE5"></span></div>%,
|
||||
' PE5 found'
|
||||
) or explain( $res->[2]->[0], 'PE5 - Unvalid identity' );
|
||||
count(2);
|
||||
|
||||
$client->logout($id);
|
||||
|
|
|
@ -18,15 +18,21 @@ my $client = LLNG::Manager::Test->new( {
|
|||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
requireToken => 0,
|
||||
checkUser => 1,
|
||||
impersonationRule => 1,
|
||||
impersonationRule => '$uid ne "msmith"',
|
||||
impersonationIdRule => '$uid ne "msmith"',
|
||||
checkUserDisplayPersistentInfo => 0,
|
||||
checkUserDisplayEmptyValues => 0,
|
||||
impersonationMergeSSOgroups => 0,
|
||||
macros => {
|
||||
test_impersonation => '"$real__user/$_user"',
|
||||
_whatToTrace =>
|
||||
'$_auth eq "SAML" ? "$_user@$_idpConfKey" : $_user',
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
## Try to authenticate with bad spoofed user
|
||||
## Try to impersonate with a bad spoofed user
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
count(1);
|
||||
my ( $host, $url, $query ) =
|
||||
|
@ -45,16 +51,133 @@ ok(
|
|||
'Auth query'
|
||||
);
|
||||
ok( $res->[2]->[0] =~ m%<span trmsg="40"></span>%, ' PE40 found' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
or explain( $res->[2]->[0], "PE40 - Bad formed user" );
|
||||
count(2);
|
||||
|
||||
my $id = expectCookie($res);
|
||||
$client->logout($id);
|
||||
|
||||
## Try to impersonate with a forbidden identity
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
count(1);
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, '#', undef, 'user', 'password', 'spoofId' );
|
||||
|
||||
$query =~ s/user=/user=rtyler/;
|
||||
$query =~ s/password=/password=rtyler/;
|
||||
$query =~ s/spoofId=/spoofId=msmith/;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Auth query'
|
||||
);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<div class="message message-negative alert"><span trmsg="5"></span></div>%,
|
||||
' PE5 found'
|
||||
) or explain( $res->[2]->[0], "PE5 - Forbidden identity" );
|
||||
count(2);
|
||||
|
||||
$id = expectCookie($res);
|
||||
$client->logout($id);
|
||||
|
||||
## An unauthorized user try to impersonate
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
count(1);
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, '#', undef, 'user', 'password', 'spoofId' );
|
||||
|
||||
$query =~ s/user=/user=msmith/;
|
||||
$query =~ s/password=/password=msmith/;
|
||||
$query =~ s/spoofId=/spoofId=rtyler/;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Auth query'
|
||||
);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<div class="message message-negative alert"><span trmsg="93"></span></div>%,
|
||||
' PE93 found'
|
||||
) or explain( $res->[2]->[0], "PE93 - Impersonation service not allowed" );
|
||||
count(2);
|
||||
|
||||
$id = expectCookie($res);
|
||||
$client->logout($id);
|
||||
|
||||
## An unauthorized user to impersonate tries to authenticate
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
count(1);
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, '#', undef, 'user', 'password', 'spoofId' );
|
||||
|
||||
$query =~ s/user=/user=msmith/;
|
||||
$query =~ s/password=/password=msmith/;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Auth query'
|
||||
);
|
||||
count(1);
|
||||
|
||||
$id = expectCookie($res);
|
||||
expectRedirection( $res, 'http://auth.example.com/' );
|
||||
|
||||
# CheckUser form
|
||||
# ------------------------
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/checkuser',
|
||||
cookie => "lemonldap=$id",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'CheckUser form',
|
||||
);
|
||||
count(1);
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, undef, '/checkuser', 'user', 'url' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
|
||||
or explain( $res->[2]->[0], 'trspan="checkUser"' );
|
||||
count(1);
|
||||
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/checkuser',
|
||||
IO::String->new($query),
|
||||
cookie => "lemonldap=$id",
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'POST checkuser'
|
||||
);
|
||||
count(1);
|
||||
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">test_impersonation</td>%,
|
||||
'Found macro test_impersonation' )
|
||||
or explain( $res->[2]->[0], 'test_impersonation' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">msmith/msmith</td>%,
|
||||
'Found msmith/msmith' )
|
||||
or explain( $res->[2]->[0], 'Found msmith/msmith' );
|
||||
count(2);
|
||||
|
||||
$client->logout($id);
|
||||
|
||||
## Try to authenticate
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
count(1);
|
||||
my ( $host, $url, $query ) =
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, '#', undef, 'user', 'password', 'spoofId' );
|
||||
|
||||
$query =~ s/user=/user=rtyler/;
|
||||
|
@ -146,7 +269,13 @@ ok( $res->[2]->[0] =~ m%<td class="text-left">real_uid</td>%, 'Found real_uid' )
|
|||
or explain( $res->[2]->[0], 'real_groups' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">rtyler</td>%, 'Found rtyler' )
|
||||
or explain( $res->[2]->[0], 'su' );
|
||||
count(14);
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">test_impersonation</td>%,
|
||||
'Found macro test_impersonation' )
|
||||
or explain( $res->[2]->[0], 'test_impersonation' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">rtyler/dwho</td>%,
|
||||
'Found rtyler/dwo' )
|
||||
or explain( $res->[2]->[0], 'Found rtyler/dwo' );
|
||||
count(16);
|
||||
|
||||
$client->logout($id);
|
||||
clean_sessions();
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
"key": "qwertyui",
|
||||
"locationRules": {
|
||||
"auth.example.com" : {
|
||||
"(?#checkUser)^/checkuser" : "$uid eq \"dwho\" or $uid eq \"rtyler\"",
|
||||
"(?#checkUser)^/checkuser" : "$uid eq \"dwho\" or $uid eq \"msmith\"",
|
||||
"(?#errors)^/lmerror/": "accept",
|
||||
"default" : "accept"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue