...
 
Commits (32)
# debian/tests/runner launch pkg-perl-autopkgtest tests for each library # debian/tests/runner launch pkg-perl-autopkgtest tests for each library
Test-Command: ./debian/tests/runner build-deps Test-Command: ./debian/tests/runner build-deps lemonldap-ng-common
Depends: @, @builddeps@, pkg-perl-autopkgtest, libmouse-perl Depends: liblemonldap-ng-common-perl, @builddeps@, pkg-perl-autopkgtest
Test-Command: ./debian/tests/runner runtime-deps Test-Command: ./debian/tests/runner build-deps lemonldap-ng-handler
Depends: @, pkg-perl-autopkgtest, libmouse-perl Depends: liblemonldap-ng-handler-perl, @builddeps@, pkg-perl-autopkgtest
Test-Command: ./debian/tests/runner build-deps lemonldap-ng-portal
Depends: liblemonldap-ng-portal-perl, @builddeps@, pkg-perl-autopkgtest
Test-Command: ./debian/tests/runner build-deps lemonldap-ng-manager
Depends: liblemonldap-ng-manager-perl, @builddeps@, pkg-perl-autopkgtest
Test-Command: ./debian/tests/runner runtime-deps lemonldap-ng-common
Depends: liblemonldap-ng-common-perl, pkg-perl-autopkgtest, libmouse-perl
Restrictions: superficial, skippable
# Disable this one: skipped
#Test-Command: ./debian/tests/runner runtime-deps lemonldap-ng-handler
#Depends: liblemonldap-ng-handler-perl, pkg-perl-autopkgtest, libmouse-perl
#Restrictions: superficial, skippable
Test-Command: ./debian/tests/runner runtime-deps lemonldap-ng-portal
Depends: liblemonldap-ng-portal-perl, pkg-perl-autopkgtest, libmouse-perl
Restrictions: superficial, skippable
Test-Command: ./debian/tests/runner runtime-deps lemonldap-ng-manager
Depends: liblemonldap-ng-manager-perl, pkg-perl-autopkgtest, libmouse-perl
Restrictions: superficial, skippable
# Use pkg-perl-autopkgtest test for runtime-deps-and-recommends # Use pkg-perl-autopkgtest test for runtime-deps-and-recommends
# Some portal suggested dependencies are added here # Some portal suggested dependencies are added here
Test-Command: /usr/share/pkg-perl-autopkgtest/runner runtime-deps-and-recommends Test-Command: /usr/share/pkg-perl-autopkgtest/runner runtime-deps-and-recommends
Depends: @, @builddeps@, pkg-perl-autopkgtest, libyaml-perl, liblog-log4perl-perl, libauthen-pam-perl, libauthen-radius-perl, libweb-id-perl, libipc-run-perl Depends: @, @builddeps@, pkg-perl-autopkgtest, libyaml-perl, liblog-log4perl-perl, libauthen-pam-perl, libauthen-radius-perl, libweb-id-perl
Restrictions: superficial
#Test-Command: ./debian/tests/runner heavy-deps #Test-Command: ./debian/tests/runner heavy-deps
#Depends: @, pkg-perl-autopkgtest, pkg-perl-autopkgtest-heavy, libmouse-perl #Depends: @, pkg-perl-autopkgtest, pkg-perl-autopkgtest-heavy, libmouse-perl
...@@ -141,6 +141,10 @@ ...@@ -141,6 +141,10 @@
"namespace": "lemonldap-ng-sessions" "namespace": "lemonldap-ng-sessions"
}, },
"locationRules": { "locationRules": {
"auth.example.com" : {
"(?#checkUser)/checkuser" : "$uid eq \"dwho\"",
"default" : "deny"
},
"manager.example.com": { "manager.example.com": {
"(?#Configuration)^/(manager\\.html|conf/)": "$uid eq \"dwho\"", "(?#Configuration)^/(manager\\.html|conf/)": "$uid eq \"dwho\"",
"(?#Notifications)^/notifications": "$uid eq \"dwho\" or $uid eq \"rtyler\"", "(?#Notifications)^/notifications": "$uid eq \"dwho\" or $uid eq \"rtyler\"",
......
...@@ -28,7 +28,7 @@ sub defaultValues { ...@@ -28,7 +28,7 @@ sub defaultValues {
'casAccessControlPolicy' => 'none', 'casAccessControlPolicy' => 'none',
'casAuthnLevel' => 1, 'casAuthnLevel' => 1,
'checkTime' => 600, 'checkTime' => 600,
'checkUserHiddenAttributes' => 'UA _2fDevices _loginHistory', 'checkUserHiddenAttributes' => '_2fDevices _loginHistory hGroups',
'checkXSS' => 1, 'checkXSS' => 1,
'confirmFormMethod' => 'post', 'confirmFormMethod' => 'post',
'cookieName' => 'lemonldap', 'cookieName' => 'lemonldap',
...@@ -64,30 +64,34 @@ sub defaultValues { ...@@ -64,30 +64,34 @@ sub defaultValues {
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256', 'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/' 'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
}, },
'gpgDb' => '', 'gpgDb' => '',
'groups' => {}, 'groups' => {},
'handlerInternalCache' => 15, 'handlerInternalCache' => 15,
'hiddenAttributes' => '_password', 'hiddenAttributes' => '_password',
'httpOnly' => 1, 'httpOnly' => 1,
'https' => -1, 'https' => -1,
'infoFormMethod' => 'get', 'idSpoofingHiddenAttributes' => '_2fDevices _loginHistory',
'issuerDBCASPath' => '^/cas/', 'idSpoofingPrefix' => 'real_',
'issuerDBCASRule' => 1, 'idSpoofingRule' => 1,
'issuerDBGetParameters' => {}, 'idSpoofingSkipEmptyValues' => 1,
'issuerDBGetPath' => '^/get/', 'infoFormMethod' => 'get',
'issuerDBGetRule' => 1, 'issuerDBCASPath' => '^/cas/',
'issuerDBOpenIDConnectPath' => '^/oauth2/', 'issuerDBCASRule' => 1,
'issuerDBOpenIDConnectRule' => 1, 'issuerDBGetParameters' => {},
'issuerDBOpenIDPath' => '^/openidserver/', 'issuerDBGetPath' => '^/get/',
'issuerDBOpenIDRule' => 1, 'issuerDBGetRule' => 1,
'issuerDBSAMLPath' => '^/saml/', 'issuerDBOpenIDConnectPath' => '^/oauth2/',
'issuerDBSAMLRule' => 1, 'issuerDBOpenIDConnectRule' => 1,
'jsRedirect' => 0, 'issuerDBOpenIDPath' => '^/openidserver/',
'krbAuthnLevel' => 3, 'issuerDBOpenIDRule' => 1,
'krbRemoveDomain' => 1, 'issuerDBSAMLPath' => '^/saml/',
'ldapAuthnLevel' => 2, 'issuerDBSAMLRule' => 1,
'ldapBase' => 'dc=example,dc=com', 'jsRedirect' => 0,
'ldapExportedVars' => { 'krbAuthnLevel' => 3,
'krbRemoveDomain' => 1,
'ldapAuthnLevel' => 2,
'ldapBase' => 'dc=example,dc=com',
'ldapExportedVars' => {
'cn' => 'cn', 'cn' => 'cn',
'mail' => 'mail', 'mail' => 'mail',
'uid' => 'uid' 'uid' => 'uid'
...@@ -241,6 +245,7 @@ sub defaultValues { ...@@ -241,6 +245,7 @@ sub defaultValues {
'samlOrganizationDisplayName' => 'Example', 'samlOrganizationDisplayName' => 'Example',
'samlOrganizationName' => 'Example', 'samlOrganizationName' => 'Example',
'samlOrganizationURL' => 'http://www.example.com', 'samlOrganizationURL' => 'http://www.example.com',
'samlOverrideIDPEntityID' => '',
'samlRelayStateTimeout' => 600, 'samlRelayStateTimeout' => 600,
'samlServiceSignatureMethod' => 'RSA_SHA1', 'samlServiceSignatureMethod' => 'RSA_SHA1',
'samlSPSSODescriptorArtifactResolutionServiceArtifact' => 'samlSPSSODescriptorArtifactResolutionServiceArtifact' =>
......
...@@ -66,7 +66,7 @@ our $issuerParameters = { ...@@ -66,7 +66,7 @@ our $issuerParameters = {
issuerDBOpenIDConnect => [qw(issuerDBOpenIDConnectActivation issuerDBOpenIDConnectPath issuerDBOpenIDConnectRule)], issuerDBOpenIDConnect => [qw(issuerDBOpenIDConnectActivation issuerDBOpenIDConnectPath issuerDBOpenIDConnectRule)],
issuerDBSAML => [qw(issuerDBSAMLActivation issuerDBSAMLPath issuerDBSAMLRule)], 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)]; our $oidcServiceParameters = [qw(oidcServiceMetaDataIssuer oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI oidcServiceMetaDataEndSessionURI oidcServiceMetaDataCheckSessionURI oidcServiceMetaDataFrontChannelURI oidcServiceMetaDataBackChannelURI oidcServiceMetaDataAuthnContext oidcServicePrivateKeySig oidcServicePublicKeySig oidcServiceKeyIdSig oidcServiceAllowDynamicRegistration oidcServiceAllowAuthorizationCodeFlow oidcServiceAllowImplicitFlow oidcServiceAllowHybridFlow oidcStorage oidcStorageOptions)];
1; 1;
...@@ -41,11 +41,11 @@ sub serviceToXML { ...@@ -41,11 +41,11 @@ sub serviceToXML {
samlOrganizationURL samlOrganizationURL
); );
if ($type eq 'idp') { if ($type and $type eq 'idp') {
$template->param( 'hideSPMetadata', 1); $template->param( 'hideSPMetadata', 1);
} }
if ($type eq 'sp') { if ($type and $type eq 'sp') {
$template->param( 'hideIDPMetadata', 1); $template->param( 'hideIDPMetadata', 1);
} }
...@@ -53,6 +53,11 @@ sub serviceToXML { ...@@ -53,6 +53,11 @@ sub serviceToXML {
$template->param( $_, $self->getValue( $_, $conf ) ); $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 # Boolean parameters
my @param_boolean = qw( my @param_boolean = qw(
samlSPSSODescriptorAuthnRequestsSigned samlSPSSODescriptorAuthnRequestsSigned
......
...@@ -780,7 +780,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.] ...@@ -780,7 +780,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'type' => 'bool' 'type' => 'bool'
}, },
'checkUserHiddenAttributes' => { 'checkUserHiddenAttributes' => {
'default' => 'UA _2fDevices _loginHistory', 'default' => '_2fDevices _loginHistory hGroups',
'type' => 'text' 'type' => 'text'
}, },
'checkXSS' => { 'checkXSS' => {
...@@ -1195,6 +1195,26 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][ ...@@ -1195,6 +1195,26 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'default' => -1, 'default' => -1,
'type' => 'trool' 'type' => 'trool'
}, },
'idSpoofing' => {
'default' => 0,
'type' => 'bool'
},
'idSpoofingHiddenAttributes' => {
'default' => '_2fDevices _loginHistory',
'type' => 'text'
},
'idSpoofingPrefix' => {
'default' => 'real_',
'type' => 'text'
},
'idSpoofingRule' => {
'default' => 1,
'type' => 'boolOrExpr'
},
'idSpoofingSkipEmptyValues' => {
'default' => 1,
'type' => 'bool'
},
'infoFormMethod' => { 'infoFormMethod' => {
'default' => 'get', 'default' => 'get',
'select' => [ { 'select' => [ {
...@@ -2865,6 +2885,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.] ...@@ -2865,6 +2885,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'default' => 'http://www.example.com', 'default' => 'http://www.example.com',
'type' => 'text' 'type' => 'text'
}, },
'samlOverrideIDPEntityID' => {
'default' => '',
'type' => 'text'
},
'samlRelayStateTimeout' => { 'samlRelayStateTimeout' => {
'default' => 600, 'default' => 600,
'type' => 'int' 'type' => 'int'
......
...@@ -416,6 +416,59 @@ sub attributes { ...@@ -416,6 +416,59 @@ sub attributes {
type => 'text', type => 'text',
documentation => 'Secret token for CheckState plugin', documentation => 'Secret token for CheckState plugin',
}, },
checkUser => {
default => 0,
type => 'bool',
documentation => 'Enable check user',
flags => 'p',
},
checkUserHiddenAttributes => {
type => 'text',
default => '_2fDevices _loginHistory hGroups',
documentation => 'Attributes to hide in CheckUser plugin',
flags => 'p',
},
checkUserDisplayPersistentInfo => {
default => 0,
type => 'bool',
documentation => 'Display persistent session info',
flags => 'p',
},
checkUserDisplayEmptyValues => {
default => 0,
type => 'bool',
documentation => 'Display session empty values',
flags => 'p',
},
idSpoofing => {
default => 0,
type => 'bool',
documentation => 'Enable IdSpoofing plugin',
flags => 'p',
},
idSpoofingPrefix => {
type => 'text',
default => 'real_',
documentation => 'Prefix to rename real session attributes',
flags => 'p',
},
idSpoofingRule => {
type => 'boolOrExpr',
default => 1,
documentation => 'IdSpoofing activation rule',
},
idSpoofingHiddenAttributes => {
type => 'text',
default => '_2fDevices _loginHistory',
documentation => 'Attributes to skip',
flags => 'p',
},
idSpoofingSkipEmptyValues => {
default => 1,
type => 'bool',
documentation => 'Skip session empty values',
flags => 'p',
},
skipRenewConfirmation => { skipRenewConfirmation => {
type => 'bool', type => 'bool',
default => 0, default => 0,
...@@ -578,30 +631,6 @@ sub attributes { ...@@ -578,30 +631,6 @@ sub attributes {
documentation => 'Enable Cross Domain Authentication', documentation => 'Enable Cross Domain Authentication',
flags => 'hp', flags => 'hp',
}, },
checkUser => {
default => 0,
type => 'bool',
documentation => 'Enable check user',
flags => 'p',
},
checkUserHiddenAttributes => {
type => 'text',
default => 'UA _2fDevices _loginHistory',
documentation => 'Attributes to hide in CheckUser plugin',
flags => 'p',
},
checkUserDisplayPersistentInfo => {
default => 0,
type => 'bool',
documentation => 'Display persistent session info',
flags => 'p',
},
checkUserDisplayEmptyValues => {
default => 0,
type => 'bool',
documentation => 'Display session empty values',
flags => 'p',
},
checkXSS => { checkXSS => {
default => 1, default => 1,
type => 'bool', type => 'bool',
...@@ -1992,6 +2021,11 @@ sub attributes { ...@@ -1992,6 +2021,11 @@ sub attributes {
default => 600, default => 600,
documentation => 'SAML timeout of relay state', documentation => 'SAML timeout of relay state',
}, },
samlOverrideIDPEntityID => {
type => 'text',
documentation => 'Override SAML EntityID when acting as an IDP',
default => '',
},
samlUseQueryStringSpecific => { samlUseQueryStringSpecific => {
default => 0, default => 0,
type => 'bool', type => 'bool',
......
...@@ -648,6 +648,18 @@ sub tree { ...@@ -648,6 +648,18 @@ sub tree {
'checkUserDisplayEmptyValues', 'checkUserDisplayEmptyValues',
] ]
}, },
{
title => 'spoofingIds',
help => 'idspoofing.html',
form => 'simpleInputContainer',
nodes => [
'idSpoofing',
'idSpoofingRule',
'idSpoofingPrefix',
'idSpoofingHiddenAttributes',
'idSpoofingSkipEmptyValues',
]
},
] ]
}, },
{ {
...@@ -997,7 +1009,8 @@ sub tree { ...@@ -997,7 +1009,8 @@ sub tree {
'samlDiscoveryProtocolPolicy', 'samlDiscoveryProtocolPolicy',
'samlDiscoveryProtocolIsPassive' 'samlDiscoveryProtocolIsPassive'
] ]
} },
'samlOverrideIDPEntityID',
] ]
} }
] ]
......
...@@ -629,6 +629,18 @@ sub tests { ...@@ -629,6 +629,18 @@ sub tests {
return 1; return 1;
}, },
# Warn if IdSpoofing plugin is enabled
checkIdSpoofing => sub {
return 1 unless ( $conf->{idSpoofing} );
return ( -1,
'"IdSpoofing" plugin is enabled!!!'
)
if ( $conf->{idSpoofing} );
# Return
return 1;
},
}; };
} }
......
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
"clickHereToForce":"انقر هنا لإجبار", "clickHereToForce":"انقر هنا لإجبار",
"checkState":"Activation", "checkState":"Activation",
"checkStateSecret":"Shared secret", "checkStateSecret":"Shared secret",
"checkUsers":"Session check", "checkUsers":"Session Check",
"checkUser":"Activation", "checkUser":"Activation",
"checkUserHiddenAttributes":"Hidden attributes", "checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session", "checkUserDisplayPersistentInfo":"Display persistent session",
...@@ -286,6 +286,12 @@ ...@@ -286,6 +286,12 @@
"hideTree":"إخفاء الشجرة", "hideTree":"إخفاء الشجرة",
"httpOnly":"الحماية بواسطة جافا سكريبت", "httpOnly":"الحماية بواسطة جافا سكريبت",
"https":"إتش تي تي بي س", "https":"إتش تي تي بي س",
"spoofingIds":"Id Spoofing",
"idSpoofing":"Activation",
"idSpoofingRule":"Use rule",
"idSpoofingHiddenAttributes":"Hidden attributes",
"idSpoofingPrefix":"Real attributes prefix",
"idSpoofingSkipEmptyValues":"Skip empty values",
"incompleteForm":"الحقول المطلوبة مفقودة", "incompleteForm":"الحقول المطلوبة مفقودة",
"index":"فهرس", "index":"فهرس",
"infoFormMethod":"طريقة للحصول على معلومات الإستمارة", "infoFormMethod":"طريقة للحصول على معلومات الإستمارة",
...@@ -969,5 +975,6 @@ ...@@ -969,5 +975,6 @@
"samlCommonDomainCookieReader":"يو آر إل القارئ", "samlCommonDomainCookieReader":"يو آر إل القارئ",
"samlCommonDomainCookieWriter":"يو آر إل الكاتب", "samlCommonDomainCookieWriter":"يو آر إل الكاتب",
"samlRelayStateTimeout":"تناوب حالة مهلة الجلسة ", "samlRelayStateTimeout":"تناوب حالة مهلة الجلسة ",
"samlUseQueryStringSpecific":"استخدام أسلوب query_string المعين" "samlUseQueryStringSpecific":"استخدام أسلوب query_string المعين",
} "samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
\ No newline at end of file }
...@@ -151,8 +151,8 @@ ...@@ -151,8 +151,8 @@
"clickHereToForce":"Click here to force", "clickHereToForce":"Click here to force",
"checkState":"Activation", "checkState":"Activation",
"checkStateSecret":"Shared secret", "checkStateSecret":"Shared secret",
"checkUsers":"Session Check",
"choiceParams":"Choice parameters", "choiceParams":"Choice parameters",
"checkUsers":"Session check",
"checkUser":"Activation", "checkUser":"Activation",
"checkUserHiddenAttributes":"Hidden attributes", "checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session", "checkUserDisplayPersistentInfo":"Display persistent session",
...@@ -286,6 +286,12 @@ ...@@ -286,6 +286,12 @@
"hideTree":"Hide tree", "hideTree":"Hide tree",
"httpOnly":"Javascript protection", "httpOnly":"Javascript protection",
"https":"HTTPS", "https":"HTTPS",
"spoofingIds":"Id Spoofing",
"idSpoofing":"Activation",
"idSpoofingRule":"Use rule",
"idSpoofingHiddenAttributes":"Hidden attributes",
"idSpoofingPrefix":"Real attributes prefix",
"idSpoofingSkipEmptyValues":"Skip empty values",
"incompleteForm":"Required fields are missing", "incompleteForm":"Required fields are missing",
"index":"Index", "index":"Index",
"infoFormMethod":"Method for info form", "infoFormMethod":"Method for info form",
...@@ -969,5 +975,6 @@ ...@@ -969,5 +975,6 @@
"samlCommonDomainCookieReader":"Reader URL", "samlCommonDomainCookieReader":"Reader URL",
"samlCommonDomainCookieWriter":"Writer URL", "samlCommonDomainCookieWriter":"Writer URL",
"samlRelayStateTimeout":"RelayState session timeout", "samlRelayStateTimeout":"RelayState session timeout",
"samlUseQueryStringSpecific":"Use specific query_string method" "samlUseQueryStringSpecific":"Use specific query_string method",
} "samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
\ No newline at end of file }
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
"clickHereToForce":"Click here to force", "clickHereToForce":"Click here to force",
"checkState":"Activation", "checkState":"Activation",
"checkStateSecret":"Shared secret", "checkStateSecret":"Shared secret",
"checkUsers":"Session check", "checkUsers":"Session Check",
"checkUser":"Activation", "checkUser":"Activation",
"checkUserHiddenAttributes":"Hidden attributes", "checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session", "checkUserDisplayPersistentInfo":"Display persistent session",
...@@ -286,6 +286,12 @@ ...@@ -286,6 +286,12 @@
"hideTree":"Hide tree", "hideTree":"Hide tree",
"httpOnly":"Javascript protection", "httpOnly":"Javascript protection",
"https":"HTTPS", "https":"HTTPS",
"spoofingIds":"Id Spoofing",
"idSpoofing":"Activation",
"idSpoofingRule":"Use rule",
"idSpoofingHiddenAttributes":"Hidden attributes",
"idSpoofingPrefix":"Real attributes prefix",
"idSpoofingSkipEmptyValues":"Skip empty values",
"incompleteForm":"Required fields are missing", "incompleteForm":"Required fields are missing",
"index":"Index", "index":"Index",
"infoFormMethod":"Method for info form", "infoFormMethod":"Method for info form",
...@@ -969,5 +975,6 @@ ...@@ -969,5 +975,6 @@
"samlCommonDomainCookieReader":"Reader URL", "samlCommonDomainCookieReader":"Reader URL",
"samlCommonDomainCookieWriter":"Writer URL", "samlCommonDomainCookieWriter":"Writer URL",
"samlRelayStateTimeout":"RelayState session timeout", "samlRelayStateTimeout":"RelayState session timeout",
"samlUseQueryStringSpecific":"Use specific query_string method" "samlUseQueryStringSpecific":"Use specific query_string method",
"samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
} }
...@@ -151,12 +151,12 @@ ...@@ -151,12 +151,12 @@
"clickHereToForce":"Cliquer ici pour forcer", "clickHereToForce":"Cliquer ici pour forcer",
"checkState":"Activation", "checkState":"Activation",
"checkStateSecret":"Secret partagé", "checkStateSecret":"Secret partagé",
"choiceParams":"Paramètres des choix",
"checkUsers":"Vérification de session", "checkUsers":"Vérification de session",
"checkUser":"Activation", "checkUser":"Activation",
"checkUserHiddenAttributes":"Attributs masqués", "checkUserHiddenAttributes":"Attributs masqués",
"checkUserDisplayPersistentInfo":"Afficher les données de session persistante", "checkUserDisplayPersistentInfo":"Afficher les données de session persistante",
"checkUserDisplayEmptyValues":"Afficher les valeurs nulles", "checkUserDisplayEmptyValues":"Afficher les valeurs nulles",
"choiceParams":"Paramètres des choix",
"chooseLogo":"Choisir le logo", "chooseLogo":"Choisir le logo",
"chooseSkin":"Choisir le thème", "chooseSkin":"Choisir le thème",
"combination":"Combinaison", "combination":"Combinaison",
...@@ -286,6 +286,12 @@ ...@@ -286,6 +286,12 @@
"hideTree":"Masquer l'arbre", "hideTree":"Masquer l'arbre",
"httpOnly":"Protection contre javascript", "httpOnly":"Protection contre javascript",
"https":"HTTPS", "https":"HTTPS",
"spoofingIds":"Usurpation d'identité",
"idSpoofing":"Activation",
"idSpoofingRule":"Règle d'utilisation",
"idSpoofingHiddenAttributes":"Attributs masqués",
"idSpoofingPrefix":"Préfix des vrais attributs",
"idSpoofingSkipEmptyValues":"Ignorer les valeurs nulles",
"incompleteForm":"Des champs requis manquent", "incompleteForm":"Des champs requis manquent",
"index":"Index", "index":"Index",
"infoFormMethod":"Méthode du formulaire d'information", "infoFormMethod":"Méthode du formulaire d'information",
...@@ -969,5 +975,6 @@ ...@@ -969,5 +975,6 @@
"samlCommonDomainCookieReader":"URL de lecture", "samlCommonDomainCookieReader":"URL de lecture",
"samlCommonDomainCookieWriter":"URL d'écriture", "samlCommonDomainCookieWriter":"URL d'écriture",
"samlRelayStateTimeout":"Durée de vie d'une session RelayState", "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"
} }
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
"clickHereToForce":"Clicca qui per forzare", "clickHereToForce":"Clicca qui per forzare",
"checkState":"Attivazione", "checkState":"Attivazione",
"checkStateSecret":"Segreto condiviso", "checkStateSecret":"Segreto condiviso",
"checkUsers":"Session check", "checkUsers":"Session Check",
"checkUser":"Activation", "checkUser":"Activation",
"checkUserHiddenAttributes":"Hidden attributes", "checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session", "checkUserDisplayPersistentInfo":"Display persistent session",
...@@ -286,6 +286,12 @@ ...@@ -286,6 +286,12 @@
"hideTree":"Nascondi l'albero", "hideTree":"Nascondi l'albero",
"httpOnly":"Protezione Javascript", "httpOnly":"Protezione Javascript",
"https":"HTTPS", "https":"HTTPS",
"spoofingIds":"Id Spoofing",
"idSpoofing":"Activation",
"idSpoofingRule":"Use rule",
"idSpoofingHiddenAttributes":"Hidden attributes",
"idSpoofingPrefix":"Real attributes prefix",
"idSpoofingSkipEmptyValues":"Skip empty values",
"incompleteForm":"Mancano campi obbligatori", "incompleteForm":"Mancano campi obbligatori",
"index":"Indice", "index":"Indice",
"infoFormMethod":"Metodo per il modulo informazioni", "infoFormMethod":"Metodo per il modulo informazioni",
...@@ -969,5 +975,6 @@ ...@@ -969,5 +975,6 @@
"samlCommonDomainCookieReader":"URL del lettore", "samlCommonDomainCookieReader":"URL del lettore",
"samlCommonDomainCookieWriter":"URL dell'autore", "samlCommonDomainCookieWriter":"URL dell'autore",
"samlRelayStateTimeout":"Timeout di sessione di RelayState", "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"
\ No newline at end of file }
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
"clickHereToForce":"Nhấp vào đây để bắt buộc", "clickHereToForce":"Nhấp vào đây để bắt buộc",
"checkState":"Kích hoạt", "checkState":"Kích hoạt",
"checkStateSecret":"Shared secret", "checkStateSecret":"Shared secret",
"checkUsers":"Session check", "checkUsers":"Session Check",
"checkUser":"Activation", "checkUser":"Activation",
"checkUserHiddenAttributes":"Hidden attributes", "checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session", "checkUserDisplayPersistentInfo":"Display persistent session",
...@@ -286,6 +286,12 @@ ...@@ -286,6 +286,12 @@
"hideTree":"Ẩn cây", "hideTree":"Ẩn cây",
"httpOnly":"Bảo vệ Javascript", "httpOnly":"Bảo vệ Javascript",
"https":"HTTPS", "https":"HTTPS",
"spoofingIds":"Id Spoofing",
"idSpoofing":"Activation",
"idSpoofingRule":"Use rule",
"idSpoofingHiddenAttributes":"Hidden attributes",
"idSpoofingPrefix":"Real attributes prefix",
"idSpoofingSkipEmptyValues":"Skip empty values",
"incompleteForm":"Các trường bắt buộc bị thiếu", "incompleteForm":"Các trường bắt buộc bị thiếu",
"index":"Chỉ mục", "index":"Chỉ mục",
"infoFormMethod":"Phương pháp cho mẫu thông tin", "infoFormMethod":"Phương pháp cho mẫu thông tin",
...@@ -969,5 +975,6 @@ ...@@ -969,5 +975,6 @@
"samlCommonDomainCookieReader":"Trình đọc URL", "samlCommonDomainCookieReader":"Trình đọc URL",
"samlCommonDomainCookieWriter":"Trình viết URL", "samlCommonDomainCookieWriter":"Trình viết URL",
"samlRelayStateTimeout":"Thời gian hết hạn phiên RelayState ", "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"
\ No newline at end of file }
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
"clickHereToForce":"Click here to force", "clickHereToForce":"Click here to force",
"checkState":"Activation", "checkState":"Activation",
"checkStateSecret":"Shared secret", "checkStateSecret":"Shared secret",
"checkUsers":"Session check", "checkUsers":"Session Check",
"checkUser":"Activation", "checkUser":"Activation",
"checkUserHiddenAttributes":"Hidden attributes", "checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session", "checkUserDisplayPersistentInfo":"Display persistent session",
...@@ -286,6 +286,12 @@ ...@@ -286,6 +286,12 @@
"hideTree":"Hide tree", "hideTree":"Hide tree",
"httpOnly":"Javascript protection", "httpOnly":"Javascript protection",
"https":"HTTPS", "https":"HTTPS",
"spoofingIds":"Id Spoofing",
"idSpoofing":"Activation",
"idSpoofingRule":"Use rule",
"idSpoofingHiddenAttributes":"Hidden attributes",
"idSpoofingPrefix":"Real attributes prefix",
"idSpoofingSkipEmptyValues":"Skip empty values",
"incompleteForm":"Required fields are missing", "incompleteForm":"Required fields are missing",
"index":"Index", "index":"Index",
"infoFormMethod":"Method for info form", "infoFormMethod":"Method for info form",
...@@ -969,5 +975,6 @@ ...@@ -969,5 +975,6 @@
"samlCommonDomainCookieReader":"Reader URL", "samlCommonDomainCookieReader":"Reader URL",
"samlCommonDomainCookieWriter":"Writer URL", "samlCommonDomainCookieWriter":"Writer URL",
"samlRelayStateTimeout":"RelayState session timeout", "samlRelayStateTimeout":"RelayState session timeout",
"samlUseQueryStringSpecific":"Use specific query_string method" "samlUseQueryStringSpecific":"Use specific query_string method",
} "samlOverrideIDPEntityID": "Override Entity ID when acting as IDP"
\ No newline at end of file }
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -100,9 +100,11 @@ lib/Lemonldap/NG/Portal/Plugins/AutoSignin.pm ...@@ -100,9 +100,11 @@ lib/Lemonldap/NG/Portal/Plugins/AutoSignin.pm
lib/Lemonldap/NG/Portal/Plugins/BruteForceProtection.pm lib/Lemonldap/NG/Portal/Plugins/BruteForceProtection.pm
lib/Lemonldap/NG/Portal/Plugins/CDA.pm lib/Lemonldap/NG/Portal/Plugins/CDA.pm
lib/Lemonldap/NG/Portal/Plugins/CheckState.pm lib/Lemonldap/NG/Portal/Plugins/CheckState.pm
lib/Lemonldap/NG/Portal/Plugins/CheckUser.pm
lib/Lemonldap/NG/Portal/Plugins/ForceAuthn.pm lib/Lemonldap/NG/Portal/Plugins/ForceAuthn.pm
lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm
lib/Lemonldap/NG/Portal/Plugins/History.pm lib/Lemonldap/NG/Portal/Plugins/History.pm
lib/Lemonldap/NG/Portal/Plugins/IdSpoofing.pm
lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm lib/Lemonldap/NG/Portal/Plugins/MailPasswordReset.pm
lib/Lemonldap/NG/Portal/Plugins/Notifications.pm lib/Lemonldap/NG/Portal/Plugins/Notifications.pm
lib/Lemonldap/NG/Portal/Plugins/PublicPages.pm lib/Lemonldap/NG/Portal/Plugins/PublicPages.pm
...@@ -323,6 +325,7 @@ site/templates/bootstrap/2fchoice.tpl ...@@ -323,6 +325,7 @@ site/templates/bootstrap/2fchoice.tpl
site/templates/bootstrap/2fregisters.tpl site/templates/bootstrap/2fregisters.tpl
site/templates/bootstrap/casBack2Url.tpl site/templates/bootstrap/casBack2Url.tpl
site/templates/bootstrap/checklogins.tpl site/templates/bootstrap/checklogins.tpl
site/templates/bootstrap/checkuser.tpl
site/templates/bootstrap/confirm.tpl site/templates/bootstrap/confirm.tpl
site/templates/bootstrap/customfooter.tpl site/templates/bootstrap/customfooter.tpl
site/templates/bootstrap/customhead.tpl site/templates/bootstrap/customhead.tpl
...@@ -499,6 +502,8 @@ t/66-CDA-already-auth.t ...@@ -499,6 +502,8 @@ t/66-CDA-already-auth.t
t/66-CDA-with-REST.t t/66-CDA-with-REST.t
t/66-CDA-with-SOAP.t t/66-CDA-with-SOAP.t
t/66-CDA.t t/66-CDA.t
t/67-CheckUser-with-token.t
t/67-CheckUser.t
t/70-2F-TOTP-with-History.t t/70-2F-TOTP-with-History.t
t/70-2F-TOTP.t t/70-2F-TOTP.t
t/70-2F-TOTP_8.t t/70-2F-TOTP_8.t
......
...@@ -91,6 +91,11 @@ qr/^($saml_sso_get_url|$saml_sso_get_url_ret|$saml_sso_post_url|$saml_sso_post_u ...@@ -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); return 0 unless ($res);
if ( $self->conf->{samlOverrideIDPEntityID} ) {
$self->lassoServer->ProviderID(
$self->conf->{samlOverrideIDPEntityID} );
}
# Single logout routes # Single logout routes
$self->addUnauthRouteFromMetaDataURL( $self->addUnauthRouteFromMetaDataURL(
"samlIDPSSODescriptorSingleLogoutServiceSOAP", "samlIDPSSODescriptorSingleLogoutServiceSOAP",
......
...@@ -564,7 +564,7 @@ sub checkIDTokenValidity { ...@@ -564,7 +564,7 @@ sub checkIDTokenValidity {
$self->logger->error("Auth time was not returned by OP $op"); $self->logger->error("Auth time was not returned by OP $op");
return 0; return 0;
} }
if ( $auth_time + $max_age > time ) { if ( time > $auth_time + $max_age ) {
$self->userLogger->error( $self->userLogger->error(
"Authentication time ($auth_time) is too old (Max age: $max_age)" "Authentication time ($auth_time) is too old (Max age: $max_age)"
); );
......
...@@ -184,7 +184,7 @@ sub loadService { ...@@ -184,7 +184,7 @@ sub loadService {
# Create Lasso server with service metadata # Create Lasso server with service metadata
my $server = $self->createServer( my $server = $self->createServer(
$service_metadata->serviceToXML( $self->conf ), $service_metadata->serviceToXML( $self->conf, ''),
$self->conf->{samlServicePrivateKeySig}, $self->conf->{samlServicePrivateKeySig},
$self->conf->{samlServicePrivateKeySigPwd}, $self->conf->{samlServicePrivateKeySigPwd},
...@@ -3072,7 +3072,7 @@ sub importRealSession { ...@@ -3072,7 +3072,7 @@ sub importRealSession {
sub metadata { sub metadata {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $type = $req->param('type'); my $type = $req->param('type') || 'all';
require Lemonldap::NG::Common::Conf::SAML::Metadata; require Lemonldap::NG::Common::Conf::SAML::Metadata;
if ( my $metadata = Lemonldap::NG::Common::Conf::SAML::Metadata->new() ) { if ( my $metadata = Lemonldap::NG::Common::Conf::SAML::Metadata->new() ) {
my $s = $metadata->serviceToXML( $self->conf, $type); my $s = $metadata->serviceToXML( $self->conf, $type);
......
...@@ -3,7 +3,7 @@ package Lemonldap::NG::Portal::Main::Constants; ...@@ -3,7 +3,7 @@ package Lemonldap::NG::Portal::Main::Constants;
use strict; use strict;
use Exporter 'import'; use Exporter 'import';
our $VERSION = '2.0.2'; our $VERSION = '2.0.3';
use constant HANDLER => 'Lemonldap::NG::Handler::PSGI::Main'; use constant HANDLER => 'Lemonldap::NG::Handler::PSGI::Main';
use constant { use constant {
...@@ -98,7 +98,7 @@ use constant { ...@@ -98,7 +98,7 @@ use constant {
PE_OIDC_SERVICE_NOT_ALLOWED => 90, PE_OIDC_SERVICE_NOT_ALLOWED => 90,
PE_OID_SERVICE_NOT_ALLOWED => 91, PE_OID_SERVICE_NOT_ALLOWED => 91,
PE_GET_SERVICE_NOT_ALLOWED => 92, PE_GET_SERVICE_NOT_ALLOWED => 92,
PE_IDSPOOFING_SERVICE_NOT_ALLOWED => 93,
}; };
# EXPORTER PARAMETERS # EXPORTER PARAMETERS
...@@ -126,7 +126,7 @@ our @EXPORT_OK = qw( PE_SENDRESPONSE PE_INFO PE_REDIRECT PE_DONE PE_OK ...@@ -126,7 +126,7 @@ our @EXPORT_OK = qw( PE_SENDRESPONSE PE_INFO PE_REDIRECT PE_DONE PE_OK
PE_REGISTERALREADYEXISTS PE_NOTOKEN PE_TOKENEXPIRED HANDLER PE_U2FFAILED PE_REGISTERALREADYEXISTS PE_NOTOKEN PE_TOKENEXPIRED HANDLER PE_U2FFAILED
PE_UNAUTHORIZEDPARTNER PE_RENEWSESSION PE_IDPCHOICE PE_WAIT PE_MUSTAUTHN PE_UNAUTHORIZEDPARTNER PE_RENEWSESSION PE_IDPCHOICE PE_WAIT PE_MUSTAUTHN
PE_MUSTHAVEMAIL PE_SAML_SERVICE_NOT_ALLOWED PE_OIDC_SERVICE_NOT_ALLOWED PE_MUSTHAVEMAIL PE_SAML_SERVICE_NOT_ALLOWED PE_OIDC_SERVICE_NOT_ALLOWED
PE_OID_SERVICE_NOT_ALLOWED PE_GET_SERVICE_NOT_ALLOWED PE_OID_SERVICE_NOT_ALLOWED PE_GET_SERVICE_NOT_ALLOWED PE_IDSPOOFING_SERVICE_NOT_ALLOWED
); );
our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK, 'import' ], ); our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK, 'import' ], );
......
...@@ -291,6 +291,7 @@ sub display { ...@@ -291,6 +291,7 @@ sub display {
REGISTER_URL => $self->conf->{registerUrl}, REGISTER_URL => $self->conf->{registerUrl},
HIDDEN_INPUTS => $self->buildHiddenForm($req), HIDDEN_INPUTS => $self->buildHiddenForm($req),
STAYCONNECTED => $self->conf->{stayConnected}, STAYCONNECTED => $self->conf->{stayConnected},
SPOOFID => $self->conf->{idSpoofing},
( (
$req->data->{customScript} $req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
......
...@@ -5,8 +5,9 @@ package Lemonldap::NG::Portal::Main::Plugin; ...@@ -5,8 +5,9 @@ package Lemonldap::NG::Portal::Main::Plugin;
use strict; use strict;
use Mouse; use Mouse;
use HTML::Template; use HTML::Template;
use Data::Dumper;
our $VERSION = '2.0.2'; our $VERSION = '2.0.3';
extends 'Lemonldap::NG::Common::Module'; extends 'Lemonldap::NG::Common::Module';
...@@ -38,13 +39,13 @@ sub _addRoute { ...@@ -38,13 +39,13 @@ sub _addRoute {
return sub { return sub {
shift; shift;
return $sub->( $self, @_ ); return $sub->( $self, @_ );
} }
} }
else { else {
return sub { return sub {
shift; shift;
return $self->$sub(@_); return $self->$sub(@_);
} }
} }
}; };
$self->p->$type( $word, $subName, $methods, $transform ); $self->p->$type( $word, $subName, $methods, $transform );
...@@ -56,6 +57,21 @@ sub loadTemplate { ...@@ -56,6 +57,21 @@ sub loadTemplate {
return $self->p->loadTemplate(@_); return $self->p->loadTemplate(@_);
} }
sub accessCtrl {
my ( $self, $req, $uri ) = @_;
my $url = $self->conf->{portal} . $uri;
$self->logger->debug("Plugin calls accessCtrl for URL: $url");
# Check access rule
my ( $vhost, $appuri ) = $url =~ m#^https?://([^/]*)(.*)#;
$vhost =~ s/:\d+$//;
$appuri ||= '/';
$self->logger->debug(
"grant function call with VH: $vhost and URI: $appuri");
return $self->p->HANDLER->grant( $req, $req->{userData}, $appuri,
undef, $vhost );
}
1; 1;
__END__ __END__
......
...@@ -26,6 +26,7 @@ our @pList = ( ...@@ -26,6 +26,7 @@ our @pList = (
checkState => '::Plugins::CheckState', checkState => '::Plugins::CheckState',
portalForceAuthn => '::Plugins::ForceAuthn', portalForceAuthn => '::Plugins::ForceAuthn',
checkUser => '::Plugins::CheckUser', checkUser => '::Plugins::CheckUser',
idSpoofing => '::Plugins::IdSpoofing',
); );
##@method list enabledPlugins ##@method list enabledPlugins
......
...@@ -44,6 +44,15 @@ sub check { ...@@ -44,6 +44,15 @@ sub check {
my ( $attrs, $array_attrs, $array_hdrs ) = ( {}, [], [] ); my ( $attrs, $array_attrs, $array_hdrs ) = ( {}, [], [] );
my $msg = my $auth = ''; my $msg = my $auth = '';
# Check access rule
unless ( $self->accessCtrl( $req, 'checkuser' ) ) {
$self->userLogger->error(
"user $req->{user} not allowed to access /checkuser");
return $self->p->lmError( $req, 403 );
}
$self->userLogger->notice(
"user $req->{user} is allowed to access /checkuser");
# Check token # Check token
if ( $self->conf->{requireToken} ) { if ( $self->conf->{requireToken} ) {
my $token = $req->param('token'); my $token = $req->param('token');
...@@ -53,7 +62,7 @@ sub check { ...@@ -53,7 +62,7 @@ sub check {
$token = $self->ott->createToken( $req->sessionInfo ); $token = $self->ott->createToken( $req->sessionInfo );
} }
unless ( $self->ott->getToken($token) ) { unless ( $self->ott->getToken($token) ) {
$self->userLogger->warn('Ask try with expired/bad token'); $self->userLogger->warn('Checkuser try with expired/bad token');
$msg = PE_TOKENEXPIRED; $msg = PE_TOKENEXPIRED;
$token = $self->ott->createToken( $req->sessionInfo ); $token = $self->ott->createToken( $req->sessionInfo );
} }
...@@ -78,26 +87,33 @@ sub check { ...@@ -78,26 +87,33 @@ sub check {
$self->logger->debug("Check requested for $req->{user}"); $self->logger->debug("Check requested for $req->{user}");
$attrs = $self->_userDatas($req); $attrs = $self->_userDatas($req);
if ( $req->error ) { if ( $req->error ) {
$msg = 'PE' . $req->{error}; $msg = 'PE' . $req->{error};
$attrs = {}; $array_attrs = [ [], [], [] ];
} }
else { else {
$msg = 'checkUser';
# Create an array of hashes for template loop # Create an array of hashes for template loop
$self->logger->debug("Delete hidden or empty attributes"); $self->logger->debug("Delete hidden or empty attributes");
foreach my $k ( sort keys %$attrs ) { if ( $self->conf->{checkUserDisplayEmptyValues} ) {
foreach my $k ( sort keys %$attrs ) {
# Ignore hidden attributes or empty values # Ignore hidden attributes
if ( $self->conf->{checkUserDisplayEmptyValues} ) {
push @$array_attrs, { key => $k, value => $attrs->{$k} } push @$array_attrs, { key => $k, value => $attrs->{$k} }
unless ( $self->hAttr =~ /\b$k\b/ ); unless ( $self->hAttr =~ /\b$k\b/ );
} }
else { }
else {
foreach my $k ( sort keys %$attrs ) {
# Ignore hidden attributes and empty values
push @$array_attrs, { key => $k, value => $attrs->{$k} } push @$array_attrs, { key => $k, value => $attrs->{$k} }
unless ( $self->hAttr =~ /\b$k\b/ or !$attrs->{$k} ); unless ( $self->hAttr =~ /\b$k\b/ or !$attrs->{$k} );
} }
} }
$msg = 'checkUser';
# ARRAY_REF = [ A_REF GROUPS, A_REF MACROS, A_REF OTHERS ]
$array_attrs = $self->_splitAttributes($array_attrs);
} }
# Check if user is allowed to access submitted URL and compute headers # Check if user is allowed to access submitted URL and compute headers
...@@ -115,7 +131,6 @@ sub check { ...@@ -115,7 +131,6 @@ sub check {
# Return VirtualHost headers # Return VirtualHost headers
$array_hdrs = $self->_headers( $req, $url ); $array_hdrs = $self->_headers( $req, $url );
} }
my $token = $self->ott->createToken( $req->sessionInfo );
# Display form # Display form
return $self->p->sendHtml( return $self->p->sendHtml(
...@@ -140,15 +155,29 @@ sub check { ...@@ -140,15 +155,29 @@ sub check {
ALERTE_AUTH => ALERTE_AUTH =>
( $auth eq 'allowed' ? 'alert-success' : 'alert-danger' ), ( $auth eq 'allowed' ? 'alert-success' : 'alert-danger' ),
HEADERS => $array_hdrs, HEADERS => $array_hdrs,
ATTRIBUTES => $array_attrs, ATTRIBUTES => $array_attrs->[2],
TOKEN => $token, MACROS => $array_attrs->[1],
GROUPS => $array_attrs->[0],
TOKEN => (
$self->conf->{requireToken}
? $self->ott->createToken( $req->sessionInfo )
: ''
)
} }
); );
} }
sub display { sub display {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $token = $self->ott->createToken( $req->sessionInfo );
# Check access rule
unless ( $self->accessCtrl( $req, 'checkuser' ) ) {
$self->userLogger->error(
"user $req->{user} not allowed to access /checkuser");
return $self->p->lmError( $req, 403 );
}
$self->userLogger->notice(
"user $req->{user} is allowed to access /checkuser");
# Display form # Display form
return $self->p->sendHtml( return $self->p->sendHtml(
...@@ -165,7 +194,11 @@ sub display { ...@@ -165,7 +194,11 @@ sub display {
? "" ? ""
: $req->{user} : $req->{user}
), ),
TOKEN => $token, TOKEN => (
$self->conf->{requireToken}
? $self->ott->createToken( $req->sessionInfo )
: ''
)
} }
); );
} }
...@@ -193,11 +226,8 @@ sub _userDatas { ...@@ -193,11 +226,8 @@ sub _userDatas {
sub _authorization { sub _authorization {
my ( $self, $req, $uri ) = @_; my ( $self, $req, $uri ) = @_;
# Check rights
my ( $vhost, $appuri ) = $uri =~ m#^https?://([^/]*)(.*)#; my ( $vhost, $appuri ) = $uri =~ m#^https?://([^/]*)(.*)#;
$vhost =~ s/:\d+$//; $vhost =~ s/:\d+$//;
$vhost = $self->p->HANDLER->resolveAlias($vhost);
$appuri ||= '/'; $appuri ||= '/';
return $self->p->HANDLER->grant( $req, $req->{sessionInfo}, $appuri, return $self->p->HANDLER->grant( $req, $req->{sessionInfo}, $appuri,
undef, $vhost ); undef, $vhost );
...@@ -212,4 +242,31 @@ sub _headers { ...@@ -212,4 +242,31 @@ sub _headers {
return $self->p->HANDLER->checkHeaders( $req, $req->{sessionInfo} ); return $self->p->HANDLER->checkHeaders( $req, $req->{sessionInfo} );
} }
sub _splitAttributes {
my ( $self, $attrs ) = @_;
my ( $grps, $mcrs, $others ) = ( [], [], [] );
my $macros = $self->{conf}->{macros};
$self->logger->debug("Dispatching attributes...");
while (@$attrs) {
my $element = shift @$attrs;
my $ok = 0;
if ( $element->{key} eq 'groups' ) {
$self->logger->debug('Key "groups" found');
my $separator = $self->{conf}->{multiValuesSeparator};
my @tmp = split /\Q$separator/, $element->{value};
$grps = [ map { { value => $_ } } sort @tmp ];
next;
}
foreach my $key ( sort keys %$macros ) {
if ( $element->{key} eq $key ) {
push @$mcrs, $element;
$ok = 1;
last;
}
}
push @$others, $element unless $ok;
}
return [ $grps, $mcrs, $others ];
}
1; 1;
package Lemonldap::NG::Portal::Plugins::IdSpoofing;
use strict;
use Mouse;
use Lemonldap::NG::Portal::Main::Constants
qw( PE_OK PE_BADCREDENTIALS PE_IDSPOOFING_SERVICE_NOT_ALLOWED );
our $VERSION = '2.0.3';
extends 'Lemonldap::NG::Portal::Main::Plugin';
# INITIALIZATION
use constant endAuth => 'run';
has rule => ( is => 'rw', default => sub {1} );
sub hAttr {
$_[0]->{conf}->{idSpoofingHiddenAttributes} . ' '
. $_[0]->{conf}->{hiddenAttributes};
}
sub init {
my ($self) = @_;
# Parse activation rule
my $hd = $self->p->HANDLER;
$self->logger->debug(
"IdSpoofing rule -> " . $self->conf->{idSpoofingRule} );
my $rule
= $hd->buildSub( $hd->substitute( $self->conf->{idSpoofingRule} ) );
unless ($rule) {
$self->error( "Bad IdSpoofing rule -> " . $hd->tsv->{jail}->error );
return 0;
}
$self->{rule} = $rule;
return 1;
}
# RUNNING METHOD
sub run {
my ( $self, $req ) = @_;
my $spoofId = $req->param('spoofId') || '';
# Skip if no submitted SpoofId
return PE_OK unless $spoofId;
# Check activation rule
unless ( $self->rule->( $req, $req->sessionInfo ) ) {
$self->userLogger->error('IdSpoofing service not authorized');
return PE_IDSPOOFING_SERVICE_NOT_ALLOWED;
}
# Fill spoof session
my ( $realSession, $spoofSession ) = ( {}, {} );
$self->logger->debug("Spoofing Id: $spoofId...");
my $spk = '';
foreach my $k ( keys %{ $req->{sessionInfo} } ) {
if ( $self->{conf}->{idSpoofingSkipEmptyValues} ) {
next unless defined $req->{sessionInfo}->{$k};
}
$spk = "$self->{conf}->{idSpoofingPrefix}$k";
unless ( $self->hAttr =~ /\b$k\b/ ) {
$realSession->{$spk} = $req->{sessionInfo}->{$k};
$self->logger->debug("-> Store $k in realSession key: $spk");
}
}
$req->{user} = $spoofId;
$spoofSession = $self->_userDatas($req);
$spoofSession = { %$spoofSession, %$realSession };
# Main session
#$self->p->updatePersistentSession( $req, $spoofSession ); #?????
$self->p->updateSession( $req, $spoofSession );
return PE_OK;
}
sub _userDatas {
my ( $self, $req ) = @_;
$req->{sessionInfo} = {};
# Search user in database
$req->steps(
[ 'getUser', 'setSessionInfo',
'setMacros', 'setGroups',
#'setPersistentSessionInfo', 'setLocalGroups'
'setLocalGroups'
]
);
if ( my $error = $self->p->process($req) ) {
if ( $error == PE_BADCREDENTIALS ) {
$self->userLogger->warn(
'IdSpoofing requested for an unvalid user ('
. $req->{user}
. ")" );
}
$self->logger->debug("Process returned error: $error");
return $req->error($error);
}
$self->logger->debug("Populating spoofed session...");
return $req->{sessionInfo};
}
1;
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
"PE90":"Access non granted on OIDC service", "PE90":"Access non granted on OIDC service",
"PE91":"Access non granted on OID service", "PE91":"Access non granted on OID service",
"PE92":"Access non granted on GET service", "PE92":"Access non granted on GET service",
"PE93":"Access non granted on IdSpoofing service",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.", "2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"قبول", "accept":"قبول",
"accessDenied":"ليس لديك إذن بالدخول لهذا التطبيق", "accessDenied":"ليس لديك إذن بالدخول لهذا التطبيق",
...@@ -146,6 +147,7 @@ ...@@ -146,6 +147,7 @@
"gotNewMessages":"لديك بعض الرسائل الجديدة", "gotNewMessages":"لديك بعض الرسائل الجديدة",
"goToPortal":"انتقل إلى البوابة", "goToPortal":"انتقل إلى البوابة",
"gplSoft":"البرمجيات الحرة التي تغطيها رخصة GPL", "gplSoft":"البرمجيات الحرة التي تغطيها رخصة GPL",
"groups_sso":"SSO GROUPS",
"headers":"HEADERS", "headers":"HEADERS",
"id":"Id", "id":"Id",
"imSure":"انا متاكد", "imSure":"انا متاكد",
...@@ -162,6 +164,7 @@ ...@@ -162,6 +164,7 @@
"logoutConfirm":"هل تريد تسجيل الخروج؟", "logoutConfirm":"هل تريد تسجيل الخروج؟",
"logoutFromOtherApp":"Logout from other applications ...", "logoutFromOtherApp":"Logout from other applications ...",
"logoutFromSP":"Logout from service providers ...", "logoutFromSP":"Logout from service providers ...",
"macros":"MACROS",
"mail":"البريد", "mail":"البريد",
"mailSent2":"تم إرسال رسالة إلى عنوان بريدك الإلكتروني.", "mailSent2":"تم إرسال رسالة إلى عنوان بريدك الإلكتروني.",
"maintenanceMode":"هذا التطبيق في صيانة، يرجى محاولة الاتصال في وقت لاحق", "maintenanceMode":"هذا التطبيق في صيانة، يرجى محاولة الاتصال في وقت لاحق",
...@@ -216,6 +219,7 @@ ...@@ -216,6 +219,7 @@
"serviceProvidedBy":"الخدمة المقدمة من قبل", "serviceProvidedBy":"الخدمة المقدمة من قبل",
"sessionsDeleted":"الجلسات التالية تم غلقها", "sessionsDeleted":"الجلسات التالية تم غلقها",
"sfaManager":"2ndFA Manager", "sfaManager":"2ndFA Manager",
"spoofId":"Spoofed Id",
"SSOSessionInactive":"جلسة الدخول الموحد غير نشطة", "SSOSessionInactive":"جلسة الدخول الموحد غير نشطة",
"stayConnected":"ابق على اتصال على هذا الجهاز", "stayConnected":"ابق على اتصال على هذا الجهاز",
"submit":"قدم", "submit":"قدم",
......
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
"PE90":"Access non granted on OIDC service", "PE90":"Access non granted on OIDC service",
"PE91":"Access non granted on OID service", "PE91":"Access non granted on OID service",
"PE92":"Access non granted on GET service", "PE92":"Access non granted on GET service",
"PE93":"Access non granted on IdSpoofing service",
"2fRegRequired":"Dieser Dienst benötigt Zwei-Faktor-Authentifizierung. Bitte legen Sie ein Gerät an und gehen dann zum Portal zurück.", "2fRegRequired":"Dieser Dienst benötigt Zwei-Faktor-Authentifizierung. Bitte legen Sie ein Gerät an und gehen dann zum Portal zurück.",
"accept":"Akzeptieren", "accept":"Akzeptieren",
"accessDenied":"Sie haben keine Zugriffsberechtigung für diese Anwendung", "accessDenied":"Sie haben keine Zugriffsberechtigung für diese Anwendung",
...@@ -146,6 +147,7 @@ ...@@ -146,6 +147,7 @@
"gotNewMessages":"Du hast neue Nachrichten", "gotNewMessages":"Du hast neue Nachrichten",
"goToPortal":"Zum Portal", "goToPortal":"Zum Portal",
"gplSoft":"Freie Software, die von der GPL-Lizenz abgedeckt wird", "gplSoft":"Freie Software, die von der GPL-Lizenz abgedeckt wird",
"groups_sso":"SSO GROUPS",
"headers":"HEADERS", "headers":"HEADERS",
"id":"ID", "id":"ID",
"imSure":"Ich bin sicher", "imSure":"Ich bin sicher",
...@@ -162,6 +164,7 @@ ...@@ -162,6 +164,7 @@
"logoutConfirm":"Willst du dich abmelden ?", "logoutConfirm":"Willst du dich abmelden ?",
"logoutFromOtherApp":"Von anderen Anwendungen abmelden ...", "logoutFromOtherApp":"Von anderen Anwendungen abmelden ...",
"logoutFromSP":"Von Dienstanbietern abmelden ...", "logoutFromSP":"Von Dienstanbietern abmelden ...",
"macros":"MACROS",
"mail":"E-Mail", "mail":"E-Mail",
"mailSent2":"Eine Nachricht wurde an deine E-Mail Adresse gesendet.", "mailSent2":"Eine Nachricht wurde an deine E-Mail Adresse gesendet.",
"maintenanceMode":"Diese Anwendung ist in Wartung, bitte versuche später eine Verbindung herzustellen", "maintenanceMode":"Diese Anwendung ist in Wartung, bitte versuche später eine Verbindung herzustellen",
...@@ -216,6 +219,7 @@ ...@@ -216,6 +219,7 @@
"serviceProvidedBy":"Dienst angeboten von", "serviceProvidedBy":"Dienst angeboten von",
"sessionsDeleted":"Die folgenden Sitzungen wurden geschlossen", "sessionsDeleted":"Die folgenden Sitzungen wurden geschlossen",
"sfaManager":"2ndFA Manager", "sfaManager":"2ndFA Manager",
"spoofId":"Spoofed Id",
"SSOSessionInactive":"SSO Sitzung inaktiv", "SSOSessionInactive":"SSO Sitzung inaktiv",
"stayConnected":"Auf diesem Gerät verbunden bleiben", "stayConnected":"Auf diesem Gerät verbunden bleiben",
"submit":"Absenden", "submit":"Absenden",
......
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
"PE90":"Access non granted on OIDC service", "PE90":"Access non granted on OIDC service",
"PE91":"Access non granted on OID service", "PE91":"Access non granted on OID service",
"PE92":"Access non granted on GET service", "PE92":"Access non granted on GET service",
"PE93":"Access non granted on IdSpoofing service",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.", "2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Accept", "accept":"Accept",
"accessDenied":"You have no access authorization for this application", "accessDenied":"You have no access authorization for this application",
...@@ -146,6 +147,7 @@ ...@@ -146,6 +147,7 @@
"gotNewMessages":"You have some new messages", "gotNewMessages":"You have some new messages",
"goToPortal":"Go to portal", "goToPortal":"Go to portal",
"gplSoft":"free software covered by the GPL license", "gplSoft":"free software covered by the GPL license",
"groups_sso":"SSO GROUPS",
"headers":"HEADERS", "headers":"HEADERS",
"id":"Id", "id":"Id",
"imSure":"I'm sure", "imSure":"I'm sure",
...@@ -162,6 +164,7 @@ ...@@ -162,6 +164,7 @@
"logoutConfirm":"Do you want to logout?", "logoutConfirm":"Do you want to logout?",
"logoutFromOtherApp":"Logout from other applications ...", "logoutFromOtherApp":"Logout from other applications ...",
"logoutFromSP":"Logout from service providers ...", "logoutFromSP":"Logout from service providers ...",
"macros":"MACROS",
"mail":"Mail", "mail":"Mail",
"mailSent2":"A message has been sent to your mail address.", "mailSent2":"A message has been sent to your mail address.",
"maintenanceMode":"This application is in maintenance, please try to connect later", "maintenanceMode":"This application is in maintenance, please try to connect later",
...@@ -216,6 +219,7 @@ ...@@ -216,6 +219,7 @@
"serviceProvidedBy":"Service provided by", "serviceProvidedBy":"Service provided by",
"sessionsDeleted":"The following sessions have been closed", "sessionsDeleted":"The following sessions have been closed",
"sfaManager":"2ndFA Manager", "sfaManager":"2ndFA Manager",
"spoofId":"Spoofed Id",
"SSOSessionInactive":"SSO session inactive", "SSOSessionInactive":"SSO session inactive",
"stayConnected": "Stay connected on this device", "stayConnected": "Stay connected on this device",
"submit":"Submit", "submit":"Submit",
......
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
"PE90":"Access non granted on OIDC service", "PE90":"Access non granted on OIDC service",
"PE91":"Access non granted on OID service", "PE91":"Access non granted on OID service",
"PE92":"Access non granted on GET service", "PE92":"Access non granted on GET service",
"PE93":"Access non granted on IdSpoofing service",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.", "2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Accept", "accept":"Accept",
"accessDenied":"You have no access authorization for this application", "accessDenied":"You have no access authorization for this application",
...@@ -146,6 +147,7 @@ ...@@ -146,6 +147,7 @@
"gotNewMessages":"You have some new messages", "gotNewMessages":"You have some new messages",
"goToPortal":"Go to portal", "goToPortal":"Go to portal",
"gplSoft":"free software covered by the GPL license", "gplSoft":"free software covered by the GPL license",
"groups_sso":"SSO GROUPS",
"headers":"HEADERS", "headers":"HEADERS",
"id":"Id", "id":"Id",
"imSure":"I'm sure", "imSure":"I'm sure",
...@@ -162,6 +164,7 @@ ...@@ -162,6 +164,7 @@
"logoutConfirm":"Do you want to logout?", "logoutConfirm":"Do you want to logout?",
"logoutFromOtherApp":"Logout from other applications ...", "logoutFromOtherApp":"Logout from other applications ...",
"logoutFromSP":"Logout from service providers ...", "logoutFromSP":"Logout from service providers ...",
"macros":"MACROS",
"mail":"Mail", "mail":"Mail",
"mailSent2":"A message has been sent to your mail address.", "mailSent2":"A message has been sent to your mail address.",
"maintenanceMode":"This application is in maintenance, please try to connect later", "maintenanceMode":"This application is in maintenance, please try to connect later",
...@@ -216,6 +219,7 @@ ...@@ -216,6 +219,7 @@
"serviceProvidedBy":"Service provided by", "serviceProvidedBy":"Service provided by",
"sessionsDeleted":"The following sessions have been closed", "sessionsDeleted":"The following sessions have been closed",
"sfaManager":"2ndFA Manager", "sfaManager":"2ndFA Manager",
"spoofId":"Spoofed Id",
"SSOSessionInactive":"SSO session inactive", "SSOSessionInactive":"SSO session inactive",
"stayConnected":"Stay connected on this device", "stayConnected":"Stay connected on this device",
"submit":"Submit", "submit":"Submit",
......
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
"PE90":"Accès non autorisé au service OIDC", "PE90":"Accès non autorisé au service OIDC",
"PE91":"Accès non autorisé au service OID", "PE91":"Accès non autorisé au service OID",
"PE92":"Accès non autorisé au service GET", "PE92":"Accès non autorisé au service GET",
"PE93":"Accès non autorisé au service IdSpoofing",
"2fRegRequired":"Ce service requiert une authentification à deux facteurs. Enregistrez un équipement ici et retournez au portail.", "2fRegRequired":"Ce service requiert une authentification à deux facteurs. Enregistrez un équipement ici et retournez au portail.",
"accept":"Accepter", "accept":"Accepter",
"accessDenied":"Vous n'avez pas les droits d'accès à cette application", "accessDenied":"Vous n'avez pas les droits d'accès à cette application"