Merge branch '2600' into 'v2.0'
RESTProxy authentication support for AuthChoice and Impersonation (Fixes #2600 & #2601) See merge request lemonldap-ng/lemonldap-ng!218
This commit is contained in:
commit
d3b8b27f0a
|
@ -29,17 +29,20 @@ and choose Proxy for authentication and users.
|
|||
|
||||
Then, go in ``Proxy parameters``:
|
||||
|
||||
- **Internal portal URL**: URL of internal portal
|
||||
- **Session service URL** (optional): Session service URL (default:
|
||||
same as previous for SOAP, same with "/session/my" for REST)
|
||||
- **Cookie name** (optional): name of the cookie of internal portal, if
|
||||
different from external portal
|
||||
- **Authentication level**: authentication level for Proxy module
|
||||
- **Use SOAP instead of REST**: use a deprecated SOAP server instead of
|
||||
a REST one (you must set it if internal portal version is < 2.0). In
|
||||
this case, "Portal URL" parameter must contain SOAP endpoint
|
||||
(generally http://auth.example.com/index.pl/sessions for 1.9 and
|
||||
earlier, http://auth.example.com/sessions for 2.0)
|
||||
- **URL**: URL of internal portal
|
||||
- **Session service URL** (optional): session service URL (default:
|
||||
same as previous for SOAP, same with "/session/my" for REST)
|
||||
- **Choice parameter** (optional): choice parameter of the internal portal if applicable
|
||||
- **Choice value** (optional): value of the choice parameter of the internal portal
|
||||
- **Cookie name** (optional): internal portal cookie name, if
|
||||
different from external portal
|
||||
- **Impersonation** (optional) : can be enabled if the internal portal provides impersonation
|
||||
|
||||
Internal portal
|
||||
~~~~~~~~~~~~~~~
|
||||
|
@ -59,6 +62,10 @@ in your lemonldap-ng.ini:
|
|||
|
||||
soapProxyUrn = urn:Lemonldap/NG/Common/CGI/SOAPService
|
||||
|
||||
.. note::
|
||||
|
||||
If the internal portal uses :doc:`Choice Authentication<authchoice>`, you must specify 'Internal portal choice parameter' and 'Internal portal choice value' depending on its configuration.
|
||||
This feature needs at least LLNG version 2.0.14
|
||||
|
||||
.. attention::
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ use constant DEFAULTCONFBACKENDOPTIONS => (
|
|||
);
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|ScopeRule|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)s)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
|
||||
our $arrayParameters = qr/^mySessionAuthorizedRWKeys$/;
|
||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Claims|JWT))|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration|OnlyDeclaredScopes)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|c(?:a(?:sS(?:rvMetaDataOptions(?:Gateway|Renew)|trictMatching)|ptcha_(?:register|login|mail)_enabled)|o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|heck(?:DevOps(?:D(?:isplayNormalizedHeaders|ownload))?|State|User|XSS)|rowdsec|da)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|E(?:rrorOn(?:ExpiredSession|MailNotFound)|nablePasswordDisplay)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|n(?:o(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|ewLocationWarning)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|to(?:tp2fUserCanRemoveKey|kenUseGlobalStorage)|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|(?:wsdlServ|findUs)er)$/;
|
||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Claims|JWT))|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration|OnlyDeclaredScopes)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|E(?:rrorOn(?:ExpiredSession|MailNotFound)|nablePasswordDisplay)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxy(?:AuthServiceImpersonation|UseSoap))|c(?:a(?:sS(?:rvMetaDataOptions(?:Gateway|Renew)|trictMatching)|ptcha_(?:register|login|mail)_enabled)|o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|heck(?:DevOps(?:D(?:isplayNormalizedHeaders|ownload))?|State|User|XSS)|rowdsec|da)|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|n(?:o(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|ewLocationWarning)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|to(?:tp2fUserCanRemoveKey|kenUseGlobalStorage)|g(?:roupsBeforeMacros|lobalLogoutTimer)|a(?:voidAssignment|ctiveTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|(?:wsdlServ|findUs)er)$/;
|
||||
|
||||
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ our $authParameters = {
|
|||
oidcParams => [qw(oidcAuthnLevel oidcRPCallbackGetParam oidcRPStateTimeout)],
|
||||
openidParams => [qw(openIdAuthnLevel openIdExportedVars openIdSecret openIdIDPList)],
|
||||
pamParams => [qw(pamAuthnLevel pamService)],
|
||||
proxyParams => [qw(proxyAuthnLevel proxyAuthService proxySessionService remoteCookieName proxyUseSoap)],
|
||||
proxyParams => [qw(proxyAuthnLevel proxyUseSoap proxyAuthService proxySessionService proxyAuthServiceChoiceParam proxyAuthServiceChoiceValue remoteCookieName proxyAuthServiceImpersonation)],
|
||||
radiusParams => [qw(radiusAuthnLevel radiusSecret radiusServer)],
|
||||
remoteParams => [qw(remotePortal remoteCookieName remoteGlobalStorage remoteGlobalStorageOptions)],
|
||||
restParams => [qw(restAuthnLevel restAuthUrl restUserDBUrl restPwdConfirmUrl restPwdModifyUrl)],
|
||||
|
|
|
@ -67,6 +67,7 @@ t/01-Lemonldap-NG-Handler-Main.t
|
|||
t/05-Lemonldap-NG-Handler-Reload.t
|
||||
t/12-Lemonldap-NG-Handler-Jail.t
|
||||
t/13-Lemonldap-NG-Handler-Fake-Safe.t
|
||||
t/14-Lemonldap-NG-Handler-Rule-Building.t
|
||||
t/50-Lemonldap-NG-Handler-SecureToken.t
|
||||
t/51-Lemonldap-NG-Handler-Zimbra.t
|
||||
t/60-Lemonldap-NG-Handler-PSGI.t
|
||||
|
|
|
@ -2987,6 +2987,16 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'proxyAuthService' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'proxyAuthServiceChoiceParam' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'proxyAuthServiceChoiceValue' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'proxyAuthServiceImpersonation' => {
|
||||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
},
|
||||
'proxySessionService' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
|
|
|
@ -3653,10 +3653,17 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
},
|
||||
|
||||
# Proxy
|
||||
proxyAuthService => { type => 'text', },
|
||||
proxySessionService => { type => 'text', },
|
||||
remoteCookieName => { type => 'text', },
|
||||
proxyUseSoap => {
|
||||
proxyAuthService => { type => 'text', },
|
||||
proxySessionService => { type => 'text', },
|
||||
proxyAuthServiceChoiceParam => { type => 'text', },
|
||||
proxyAuthServiceChoiceValue => { type => 'text', },
|
||||
proxyAuthServiceImpersonation => {
|
||||
type => 'bool',
|
||||
default => 0,
|
||||
documentation => 'Enable internal portal Impersonation',
|
||||
},
|
||||
remoteCookieName => { type => 'text', },
|
||||
proxyUseSoap => {
|
||||
type => 'bool',
|
||||
default => 0,
|
||||
documentation => 'Use SOAP instead of REST',
|
||||
|
|
|
@ -367,11 +367,21 @@ sub tree {
|
|||
{
|
||||
title => 'proxyParams',
|
||||
help => 'authproxy.html',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'proxyAuthnLevel', 'proxyAuthService',
|
||||
'proxySessionService', 'remoteCookieName',
|
||||
'proxyUseSoap'
|
||||
'proxyAuthnLevel',
|
||||
'proxyUseSoap',
|
||||
{
|
||||
title => 'proxyInternalPortal',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'proxyAuthService',
|
||||
'proxySessionService',
|
||||
'proxyAuthServiceChoiceParam',
|
||||
'proxyAuthServiceChoiceValue',
|
||||
'remoteCookieName',
|
||||
'proxyAuthServiceImpersonation',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ use Lemonldap::NG::Common::Regexp;
|
|||
use Lemonldap::NG::Handler::Main;
|
||||
use Lemonldap::NG::Common::Util qw(getSameSite);
|
||||
|
||||
our $VERSION = '2.0.12';
|
||||
our $VERSION = '2.0.14';
|
||||
|
||||
## @method hashref tests(hashref conf)
|
||||
# Return a hash ref where keys are the names of the tests and values
|
||||
|
@ -738,8 +738,8 @@ sub tests {
|
|||
return ( 1,
|
||||
"Impersonation and ContextSwitching are simultaneously enabled"
|
||||
)
|
||||
if ( $conf->{impersonationRule}
|
||||
&& $conf->{contextSwitchingRule} );
|
||||
if ( $conf->{impersonationRule}
|
||||
and $conf->{contextSwitchingRule} );
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -1024,6 +1024,25 @@ sub tests {
|
|||
if ( $conf->{authentication} eq 'Choice'
|
||||
and scalar keys %{ $conf->{authChoiceModules} } == 0 );
|
||||
return 1;
|
||||
},
|
||||
|
||||
# Internal portal URL must be defined with Proxy authentication
|
||||
authProxy => sub {
|
||||
return ( 0,
|
||||
'Proxy authentication enabled without internal portal URL' )
|
||||
if ( $conf->{authentication} eq 'Proxy'
|
||||
and !$conf->{proxyAuthService} );
|
||||
return 1;
|
||||
},
|
||||
|
||||
# Warn if Impersonation and proxyAuthServiceImpersonation are simultaneously enabled
|
||||
impersonationProxy => sub {
|
||||
return ( -1,
|
||||
'Impersonation and internal portal Impersonation are simultaneously enabled'
|
||||
)
|
||||
if ( $conf->{impersonationRule}
|
||||
and $conf->{proxyAuthServiceImpersonation} );
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"متغيرات للنشر",
|
||||
"previous":"السابق",
|
||||
"privateKey":"مفتاح الخاصة",
|
||||
"proxyAuthService":"يو آر إل البوابة الداخلي",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"مستوى إثبات الهوية",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"معايير البروكسي",
|
||||
"proxySessionService":"رابط اليورال لخدمة الجلسة",
|
||||
"proxyUseSoap":"استخدام سواب بدلا من ريست",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Variables to post",
|
||||
"previous":"Previous",
|
||||
"privateKey":"Private key",
|
||||
"proxyAuthService":"Internal portal URL",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"Authentication level",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"Proxy parameters",
|
||||
"proxySessionService":"Session service URL",
|
||||
"proxyUseSoap":"Use SOAP instead of REST",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Variables to post",
|
||||
"previous":"Previous",
|
||||
"privateKey":"Private key",
|
||||
"proxyAuthService":"Internal portal URL",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"Authentication level",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"Proxy parameters",
|
||||
"proxySessionService":"Session service URL",
|
||||
"proxyUseSoap":"Use SOAP instead of REST",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Variables to post",
|
||||
"previous":"Previous",
|
||||
"privateKey":"Clave privada",
|
||||
"proxyAuthService":"URL de portal interno",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"Nivel de autentificación",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"Parámetros del proxy",
|
||||
"proxySessionService":"Session service URL",
|
||||
"proxyUseSoap":"Utilizar SOAP en lugar de REST",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Variables à poster",
|
||||
"previous":"Précédente",
|
||||
"privateKey":"Clef privée",
|
||||
"proxyAuthService":"URL du portail interne",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Paramètre du choix d'authentification",
|
||||
"proxyAuthServiceChoiceValue":"Valeur du choix d'authentification",
|
||||
"proxyAuthServiceImpersonation":"Simulation d'identité",
|
||||
"proxyAuthnLevel":"Niveau d'authentification",
|
||||
"proxyInternalPortal":"Portail interne",
|
||||
"proxyParams":"Paramètres Proxy",
|
||||
"proxySessionService":"URL du service de session",
|
||||
"proxyUseSoap":"Utiliser SOAP au lieu de REST",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Variabili da inviare",
|
||||
"previous":"Precedente",
|
||||
"privateKey":"Chiave privata",
|
||||
"proxyAuthService":"URL del portale interno",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"Livello di autenticazione",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"Parametri Proxy",
|
||||
"proxySessionService":"URL del servizio di sessione",
|
||||
"proxyUseSoap":"Usa SOAP invece di REST",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Zmienne do opublikowania",
|
||||
"previous":"Poprzedni",
|
||||
"privateKey":"Prywatny klucz",
|
||||
"proxyAuthService":"Wewnętrzny adres URL portalu",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"Poziom uwierzytelnienia",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"Parametry proxy",
|
||||
"proxySessionService":"Adres URL usługi sesji",
|
||||
"proxyUseSoap":"Użyj SOAP zamiast REST",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Gönderilecek değişkenler",
|
||||
"previous":"Önceki",
|
||||
"privateKey":"Özel anahtar",
|
||||
"proxyAuthService":"Dahili portal URL'si",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"Doğrulama seviyesi",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"Proxy parametreleri",
|
||||
"proxySessionService":"Oturum servis URL'si",
|
||||
"proxyUseSoap":"REST yerine SOAP kullan",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Các biến gửi lên",
|
||||
"previous":"Trước",
|
||||
"privateKey":"Khóa cá nhân",
|
||||
"proxyAuthService":"URL cổng nội bộ",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"Mức xác thực",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"Các tham số proxy",
|
||||
"proxySessionService":"URL dịch vụ phiên",
|
||||
"proxyUseSoap":"Sử dụng SOAP thay vì REST",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"Variables to post",
|
||||
"previous":"Previous",
|
||||
"privateKey":"Private key",
|
||||
"proxyAuthService":"Internal portal URL",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"认证等级",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"Proxy parameters",
|
||||
"proxySessionService":"Session service URL",
|
||||
"proxyUseSoap":"Use SOAP instead of REST",
|
||||
|
|
|
@ -821,8 +821,12 @@
|
|||
"postedVars":"要發佈的變數",
|
||||
"previous":"前一個",
|
||||
"privateKey":"私鑰",
|
||||
"proxyAuthService":"內部首頁 URL",
|
||||
"proxyAuthService":"URL",
|
||||
"proxyAuthServiceChoiceParam":"Choice parameter",
|
||||
"proxyAuthServiceChoiceValue":"Choice value",
|
||||
"proxyAuthServiceImpersonation":"Impersonation",
|
||||
"proxyAuthnLevel":"驗證等級",
|
||||
"proxyInternalPortal":"Internal Portal",
|
||||
"proxyParams":"代理伺服器參數",
|
||||
"proxySessionService":"工作階段服務 URL",
|
||||
"proxyUseSoap":"使用 SOAP 而非 REST",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -512,6 +512,7 @@ t/24-AuthKerberos.t
|
|||
t/25-AuthSlave-with-Choice.t
|
||||
t/25-AuthSlave-with-Credentials.t
|
||||
t/26-AuthRemote.t
|
||||
t/27-AuthProxy-with-choice.t
|
||||
t/27-AuthProxy.t
|
||||
t/28-AuthChoice-and-password.t
|
||||
t/28-AuthChoice-with-captcha.t
|
||||
|
@ -576,6 +577,8 @@ t/32-OIDC-ClaimTypes.t
|
|||
t/32-OIDC-ClientCredentials-Grant.t
|
||||
t/32-OIDC-Code-Flow-with-2F-UpgradeOnly.t
|
||||
t/32-OIDC-Code-Flow-with-2F.t
|
||||
t/32-OIDC-Grant-Type-OAuth2-Handler-Rules.t
|
||||
t/32-OIDC-Grant-Type-Rules.t
|
||||
t/32-OIDC-Hooks.t
|
||||
t/32-OIDC-Macro.t
|
||||
t/32-OIDC-Offline-Session.t
|
||||
|
|
|
@ -4,28 +4,35 @@ use strict;
|
|||
use JSON;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Common::UserAgent;
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(PE_OK PE_ERROR PE_BADCREDENTIALS);
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||
PE_OK
|
||||
PE_ERROR
|
||||
PE_BADCREDENTIALS
|
||||
);
|
||||
use Lemonldap::NG::Common::FormEncode;
|
||||
|
||||
our $VERSION = '2.0.12';
|
||||
our $VERSION = '2.0.14';
|
||||
|
||||
has ua => ( is => 'rw' );
|
||||
has ua => ( is => 'rw' );
|
||||
has sessionService => ( is => 'rw' );
|
||||
|
||||
# INITIALIZATION
|
||||
|
||||
sub init {
|
||||
my ($self) = @_;
|
||||
$self->conf->{remoteCookieName} ||= $self->conf->{cookieName};
|
||||
$self->conf->{proxySessionService} ||=
|
||||
$self->conf->{proxyAuthService} . '/session/my';
|
||||
$self->conf->{proxySessionService} =~ s#/*$##;
|
||||
$self->ua( Lemonldap::NG::Common::UserAgent->new( $self->conf ) );
|
||||
$self->ua->default_header( Accept => 'application/json' );
|
||||
|
||||
unless ( defined $self->conf->{proxyAuthService} ) {
|
||||
$self->error("Missing proxyAuthService parameter");
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $sessionService = $self->conf->{proxySessionService}
|
||||
|| $self->conf->{proxyAuthService} . '/session/my';
|
||||
$sessionService =~ s#/*$##;
|
||||
$self->sessionService($sessionService);
|
||||
$self->ua( Lemonldap::NG::Common::UserAgent->new( $self->conf ) );
|
||||
$self->ua->default_header( Accept => 'application/json' );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -37,8 +44,25 @@ sub getUser {
|
|||
return PE_OK if ( $req->data->{_proxyQueryDone} );
|
||||
$self->logger->debug(
|
||||
'Proxy push auth to ' . $self->conf->{proxyAuthService} );
|
||||
my $resp = $self->ua->post( $self->conf->{proxyAuthService},
|
||||
{ user => $req->{user}, password => $req->data->{password} } );
|
||||
my $resp = $self->ua->post(
|
||||
$self->conf->{proxyAuthService},
|
||||
{
|
||||
user => $req->{user},
|
||||
password => $req->data->{password},
|
||||
(
|
||||
$self->conf->{proxyAuthServiceChoiceParam}
|
||||
&& $self->conf->{proxyAuthServiceChoiceValue}
|
||||
? ( $self->conf->{proxyAuthServiceChoiceParam} =>
|
||||
$self->conf->{proxyAuthServiceChoiceValue} )
|
||||
: ()
|
||||
),
|
||||
(
|
||||
$self->conf->{proxyAuthServiceImpersonation} && $req->param('spoofId')
|
||||
? ( spoofId => $req->param('spoofId') )
|
||||
: ()
|
||||
)
|
||||
}
|
||||
);
|
||||
unless ( $resp->is_success ) {
|
||||
$self->logger->error(
|
||||
'Unable to query authentication service: ' . $resp->status_line );
|
||||
|
@ -75,7 +99,7 @@ sub setSessionInfo {
|
|||
my ( $self, $req ) = @_;
|
||||
return PE_OK if ( $req->data->{_setSessionInfoDone} );
|
||||
my $q = HTTP::Request->new(
|
||||
GET => $self->conf->{proxySessionService} . '/global',
|
||||
GET => $self->sessionService() . '/global',
|
||||
[
|
||||
Cookie => $req->sessionInfo->{_proxyCookies},
|
||||
Accept => 'application/json'
|
||||
|
@ -97,7 +121,7 @@ sub setSessionInfo {
|
|||
$req->{sessionInfo}->{$_} ||= $res->{$_} unless (/^_/);
|
||||
}
|
||||
$req->data->{_setSessionInfoDone}++;
|
||||
|
||||
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
|
@ -113,7 +137,7 @@ sub authLogout {
|
|||
]
|
||||
);
|
||||
my $resp = $self->ua->request($q);
|
||||
|
||||
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Display functions for LemonLDAP::NG Portal
|
||||
package Lemonldap::NG::Portal::Main::Display;
|
||||
|
||||
our $VERSION = '2.0.12';
|
||||
our $VERSION = '2.0.14';
|
||||
|
||||
package Lemonldap::NG::Portal::Main;
|
||||
use strict;
|
||||
|
@ -391,7 +391,8 @@ sub display {
|
|||
REGISTER_URL => $self->conf->{registerUrl},
|
||||
HIDDEN_INPUTS => $self->buildHiddenForm($req),
|
||||
STAYCONNECTED => $self->conf->{stayConnected},
|
||||
IMPERSONATION => $self->conf->{impersonationRule},
|
||||
IMPERSONATION => $self->conf->{impersonationRule}
|
||||
|| $self->conf->{proxyAuthServiceImpersonation},
|
||||
(
|
||||
$req->data->{customScript}
|
||||
? ( CUSTOM_SCRIPT => $req->data->{customScript} )
|
||||
|
|
71
lemonldap-ng-portal/t/27-AuthProxy-with-choice.t
Normal file
71
lemonldap-ng-portal/t/27-AuthProxy-with-choice.t
Normal file
|
@ -0,0 +1,71 @@
|
|||
use Test::More;
|
||||
use strict;
|
||||
use IO::String;
|
||||
use LWP::UserAgent;
|
||||
|
||||
my $res;
|
||||
require 't/test-lib.pm';
|
||||
|
||||
my $client = LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => 'error',
|
||||
useSafeJail => 1,
|
||||
authentication => 'Proxy',
|
||||
userDB => 'Same',
|
||||
proxyAuthService => 'http://auth.example.com',
|
||||
proxyAuthServiceChoiceParam => 'lmAuth',
|
||||
proxyAuthServiceChoiceValue => '2_Password',
|
||||
proxyAuthServiceImpersonation => 1
|
||||
}
|
||||
}
|
||||
);
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get menu' );
|
||||
ok( $res->[2]->[0] =~ m#<input name="spoofId" type="text"#,
|
||||
'SpoofId input found'
|
||||
) or explain( $res->[2]->[0], 'SpoofId' );
|
||||
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new('user=dwho&password=dwho&spoofId=rtyler'),
|
||||
length => 38
|
||||
),
|
||||
'Auth query'
|
||||
);
|
||||
expectOK($res);
|
||||
my $id = expectCookie($res);
|
||||
|
||||
$client->logout($id);
|
||||
clean_sessions();
|
||||
|
||||
count(11);
|
||||
done_testing( count() );
|
||||
|
||||
# Redefine LWP methods for tests
|
||||
no warnings 'redefine';
|
||||
|
||||
sub LWP::UserAgent::request {
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
unless ( $req->uri->as_string =~
|
||||
m%http://auth.example.com(?:/session/my/global|\?logout=1)% )
|
||||
{
|
||||
ok( $req->content() =~ m%user=dwho%, 'User found' )
|
||||
or print STDERR Dumper( $req->content() );
|
||||
ok( $req->content() =~ m%password=dwho%, 'Password found' )
|
||||
or print STDERR Dumper( $req->content() );
|
||||
ok( $req->content() =~ m%lmAuth=2_Password%, 'ChoiceParam found' )
|
||||
or print STDERR Dumper( $req->content() );
|
||||
ok( $req->content() =~ m%spoofId=rtyler%, 'SpoofId found' )
|
||||
or print STDERR Dumper( $req->content() );
|
||||
}
|
||||
|
||||
my $httpResp;
|
||||
my $s =
|
||||
'{"error":"0","id":"6e30af4ffa5689b3e49a104d1b160d316db2b2161a0f45776994eed19dbdc101","result":1}';
|
||||
$httpResp = HTTP::Response->new( 200, 'OK' );
|
||||
$httpResp->header( 'Content-Type', 'application/json' );
|
||||
$httpResp->header( 'Content-Length', length($s) );
|
||||
$httpResp->content($s);
|
||||
return $httpResp;
|
||||
}
|
|
@ -10,11 +10,11 @@ SKIP: {
|
|||
skip 'REMOTELLNG is not set', $maintests unless ( $ENV{REMOTELLNG} );
|
||||
my $client = LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => 'error',
|
||||
useSafeJail => 1,
|
||||
authentication => 'Proxy',
|
||||
userDB => 'Same',
|
||||
soapAuthService => $ENV{REMOTELLNG},
|
||||
logLevel => 'error',
|
||||
useSafeJail => 1,
|
||||
authentication => 'Proxy',
|
||||
userDB => 'Same',
|
||||
proxyAuthService => $ENV{REMOTELLNG},
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue
Block a user