Merge branch 'fix-idprules-oidc-2753' into 'v2.0'

Add IDP resolution rules for CAS/OIDC (#2753)

See merge request lemonldap-ng/lemonldap-ng!267
This commit is contained in:
Maxime Besson 2022-05-19 15:00:44 +00:00
commit 694fb4e440
27 changed files with 362 additions and 79 deletions

View File

@ -63,23 +63,48 @@ Then, go in ``CAS parameters``:
- **Authentication level**: authentication level for this module. - **Authentication level**: authentication level for this module.
Then create the list of CAS servers in the manager. For each, set: Then create the list of CAS servers in the manager.
Options
~~~~~~~
- **Server URL** *(required)*: CAS server URL (must use https://) - **Server URL** *(required)*: CAS server URL (must use https://)
- **Renew authentication** *(default: disabled)*: force authentication - **Renew authentication** *(default: disabled)*: force authentication
renewal on CAS server renewal on CAS server
- **Gateways authentication** *(default: disabled)*: force transparent - **Gateways authentication** *(default: disabled)*: force transparent
authentication on CAS server authentication on CAS server
Proxied services
~~~~~~~~~~~~~~~~
In this section, set the list of services for which a proxy ticket is
requested:
- **Key**: Service ID
- **Value** Service URL (CAS service identifier)
Display
~~~~~~~
- **Display Name**: Name to display. Required if you have more than 1 - **Display Name**: Name to display. Required if you have more than 1
CAS server declared CAS server declared
- **Icon**: Path to CAS Server icon. Used only if you have more than 1 - **Icon**: Path to CAS Server icon. Used only if you have more than 1
CAS server declared CAS server declared
- **Order**: Number to sort CAS Servers display - **Resolution Rule**: rule that will be applied to preselect a CAS server for
- **Proxied services**: list of services for which a proxy ticket is a user. You have access to all environment variable *(like user IP address)*
requested: and all session keys.
- **Key**: Service ID For example, to preselect this server for users coming from 129.168.0.0/16
- **Value** Service URL (CAS service identifier) network
::
$ENV{REMOTE_ADDR} =~ /^192\.168/
To preselect this server when the ``MY_SRV`` :doc:`choice <authchoice>` is selected ::
$_choice eq "MY_SRV"
- **Order**: Number to sort CAS Servers display
.. tip:: .. tip::

View File

@ -210,42 +210,59 @@ So you can define by example:
Options Options
^^^^^^^ ^^^^^^^
- **Configuration**: Configuration
"""""""""""""
- **Configuration endpoint**: URL of OP configuration endpoint - **Configuration endpoint**: URL of OP configuration endpoint
- **JWKS data timeout**: After this time, LL::NG will do a request - **JWKS data timeout**: After this time, LL::NG will do a request
to get a fresh version of JWKS data. Set to 0 to disable it. to get a fresh version of JWKS data. Set to 0 to disable it.
- **Client ID**: Client ID given by OP - **Client ID**: Client ID given by OP
- **Client secret**: Client secret given by OP - **Client secret**: Client secret given by OP
- **Store ID token**: Allows one to store the ID Token (JWT) inside - **Store ID token**: Allows one to store the ID Token (JWT) inside
user session. Do not enable it unless you need to replay this token user session. Do not enable it unless you need to replay this token
on an application, or if you need the id_token_hint parameter when on an application, or if you need the id_token_hint parameter when
using logout. using logout.
- **Protocol**: Protocol
""""""""
- **Scope**: Value of scope parameter (example: openid profile). The
``openid`` scope is mandatory.
- **Display**: Value of display parameter (example: page)
- **Prompt**: Value of prompt parameter (example: consent)
- **Max age**: Value of max_age parameter (example: 3600)
- **UI locales**: Value of ui_locales parameter (example: en-GB en
fr-FR fr)
- **ACR values**: Value acr_values parameters (example: loa-1)
- **Token endpoint authentication method**: Choice between
``client_secret_post`` and ``client_secret_basic``
- **Check JWT signature**: Set to 0 to disable JWT signature
checking
- **ID Token max age**: If defined, LL::NG will check the ID Token
date and reject it if too old
- **Use Nonce**: If enabled, a nonce will be sent, and verified from
the ID Token
- **Scope**: Value of scope parameter (example: openid profile). The Display
``openid`` scope is mandatory. """""""
- **Display**: Value of display parameter (example: page)
- **Prompt**: Value of prompt parameter (example: consent)
- **Max age**: Value of max_age parameter (example: 3600)
- **UI locales**: Value of ui_locales parameter (example: en-GB en
fr-FR fr)
- **ACR values**: Value acr_values parameters (example: loa-1)
- **Token endpoint authentication method**: Choice between
``client_secret_post`` and ``client_secret_basic``
- **Check JWT signature**: Set to 0 to disable JWT signature
checking
- **ID Token max age**: If defined, LL::NG will check the ID Token
date and reject it if too old
- **Use Nonce**: If enabled, a nonce will be sent, and verified from
the ID Token
- **Display**: - **Display name**: Name of the application
- **Logo**: Logo of the application
- **Resolution Rule**: rule that will be applied to preselect an OP
for a user. You have access to all environment variable *(like user
IP address)* and all session keys.
- **Display name**: Name of the application For example, to preselect this OP for users coming from 129.168.0.0/16
- **Logo**: Logo of the application network
- **Order**: Number to sort buttons
::
$ENV{REMOTE_ADDR} =~ /^192\.168/
To preselect this OP when the ``MY_OP`` :doc:`choice <authchoice>` is selected ::
$_choice eq "MY_OP"
- **Order**: Number to sort buttons
.. attention:: .. attention::
@ -254,4 +271,4 @@ Options
with ``verify_hostname => 0`` and ``SSL_verify_mode => 0``. with ``verify_hostname => 0`` and ``SSL_verify_mode => 0``.
Go to: ``General Parameters > Advanced Parameters > Security > SSL options for server requests`` Go to: ``General Parameters > Advanced Parameters > Security > SSL options for server requests``

View File

@ -111,20 +111,6 @@ For each attribute, you can set:
Options Options
^^^^^^^ ^^^^^^^
General options
'''''''''''''''
- **Resolution Rule**: rule that will be applied to preselect an IDP
for a user. You have access to all environment variable *(like user
IP address)* and all session keys.
For example, to preselect this IDP for users coming from 129.168.0.0/16
network and member of "admin" group:
::
$ENV{REMOTE_ADDR} =~ /^192\.168/ and $groups =~ /\badmin\b/
Authentication request Authentication request
'''''''''''''''''''''' ''''''''''''''''''''''
@ -212,8 +198,6 @@ Used only if at least 2 SAML Identity Providers are declared
- **Display name**: Name of the IDP - **Display name**: Name of the IDP
- **Logo**: Logo of the IDP - **Logo**: Logo of the IDP
- **Order**: Number used for sorting IDP display
.. tip:: .. tip::
@ -222,6 +206,23 @@ Used only if at least 2 SAML Identity Providers are declared
icon file name directly in the field and copy the logo file in portal icon file name directly in the field and copy the logo file in portal
icons directory icons directory
- **Resolution Rule**: rule that will be applied to preselect an IDP
for a user. You have access to all environment variable *(like user
IP address)* and all session keys.
For example, to preselect this IDP for users coming from 129.168.0.0/16
network
::
$ENV{REMOTE_ADDR} =~ /^192\.168/
To preselect this IDP when the ``MY_IDP`` :doc:`choice <authchoice>` is selected ::
$_choice eq "MY_IDP"
- **Order**: Number used for sorting IDP display
.. |image0| image:: /documentation/manager-saml-metadata.png .. |image0| image:: /documentation/manager-saml-metadata.png
:class: align-center :class: align-center
.. |image1| image:: /documentation/manager-saml-attributes.png .. |image1| image:: /documentation/manager-saml-attributes.png

View File

@ -25,8 +25,8 @@ our $doubleHashKeys = 'issuerDBGetParameters';
our $simpleHashKeys = '(?:(?:c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)|l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|(?:(?:d(?:emo|bi)|webID)E|e)xportedVar|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|OPMetaDataJ(?:SON|WKS))|penIdExportedVars)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|S(?:MTPTLSOpts|SLVarIf))'; our $simpleHashKeys = '(?:(?:c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|heckUserHiddenHeader|ombModule)|l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|f(?:indUser(?:Exclud|Search)ingAttribute|acebookExportedVar)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|(?:(?:d(?:emo|bi)|webID)E|e)xportedVar|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|OPMetaDataJ(?:SON|WKS))|penIdExportedVars)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|S(?:MTPTLSOpts|SLVarIf))';
our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s'; our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:(?:UserAttribut|Servic|Rul)e|AuthnLevel)|(?:ExportedVar|Macro)s)'; our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:(?:UserAttribut|Servic|Rul)e|AuthnLevel)|(?:ExportedVar|Macro)s)';
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)'; our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:Re(?:solutionRule|new)|ProxiedServices|DisplayName|SortNumber|Gateway|Icon|Url)|ExportedVars)';
our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))'; our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|(?:ResolutionRul|MaxAg)e|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues)|ExportedVars|J(?:SON|WKS))';
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Expiration|SignAlg|Claims|JWT)|uth(?:orizationCodeExpiration|nLevel)|dditionalAudiences)|I(?:DToken(?:ForceClaims|Expiration|SignAlg)|con)|R(?:e(?:directUris|freshToken|quirePKCE)|ule)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|UserI(?:nfoSignAlg|DAttr)|OfflineSessionExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims)|(?:ExportedVar|ScopeRule|Macro)s)'; our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:A(?:llow(?:(?:ClientCredentials|Password)Grant|Offline)|ccessToken(?:Expiration|SignAlg|Claims|JWT)|uth(?:orizationCodeExpiration|nLevel)|dditionalAudiences)|I(?:DToken(?:ForceClaims|Expiration|SignAlg)|con)|R(?:e(?:directUris|freshToken|quirePKCE)|ule)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|UserI(?:nfoSignAlg|DAttr)|OfflineSessionExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims)|(?:ExportedVar|ScopeRule|Macro)s)';
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ign(?:S[LS]OMessage|atureMethod)|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)'; our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ign(?:S[LS]OMessage|atureMethod)|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:S(?:ign(?:S[LS]OMessage|atureMethod)|essionNotOnOrAfterTimeout)|N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|AuthnLevel|ForceUTF8)|(?:ExportedAttribute|Macro)s|XML)'; our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:S(?:ign(?:S[LS]OMessage|atureMethod)|essionNotOnOrAfterTimeout)|N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|AuthnLevel|ForceUTF8)|(?:ExportedAttribute|Macro)s|XML)';

View File

@ -797,6 +797,10 @@ sub attributes {
'default' => 0, 'default' => 0,
'type' => 'bool' 'type' => 'bool'
}, },
'casSrvMetaDataOptionsResolutionRule' => {
'default' => '',
'type' => 'longtext'
},
'casSrvMetaDataOptionsSortNumber' => { 'casSrvMetaDataOptionsSortNumber' => {
'type' => 'int' 'type' => 'int'
}, },
@ -2277,6 +2281,10 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
'oidcOPMetaDataOptionsPrompt' => { 'oidcOPMetaDataOptionsPrompt' => {
'type' => 'text' 'type' => 'text'
}, },
'oidcOPMetaDataOptionsResolutionRule' => {
'default' => '',
'type' => 'longtext'
},
'oidcOPMetaDataOptionsScope' => { 'oidcOPMetaDataOptionsScope' => {
'default' => 'openid profile', 'default' => 'openid profile',
'type' => 'text' 'type' => 'text'

View File

@ -3673,6 +3673,10 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
type => 'int', type => 'int',
documentation => 'Number to sort buttons', documentation => 'Number to sort buttons',
}, },
casSrvMetaDataOptionsResolutionRule => {
type => 'longtext',
default => '',
},
# Fake attribute: used by manager REST API to agglomerate all nodes # Fake attribute: used by manager REST API to agglomerate all nodes
# related to a CAS IDP partner # related to a CAS IDP partner
@ -4372,6 +4376,10 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
oidcOPMetaDataOptionsIcon => { type => 'text', }, oidcOPMetaDataOptionsIcon => { type => 'text', },
oidcOPMetaDataOptionsStoreIDToken => { type => 'bool', default => 0 }, oidcOPMetaDataOptionsStoreIDToken => { type => 'bool', default => 0 },
oidcOPMetaDataOptionsSortNumber => { type => 'int', }, oidcOPMetaDataOptionsSortNumber => { type => 'int', },
oidcOPMetaDataOptionsResolutionRule => {
type => 'longtext',
default => '',
},
# OpenID Connect relying parties # OpenID Connect relying parties
oidcRPMetaDataExportedVars => { oidcRPMetaDataExportedVars => {

View File

@ -82,7 +82,6 @@ sub cTrees {
help => 'authsaml.html#options', help => 'authsaml.html#options',
form => 'simpleInputContainer', form => 'simpleInputContainer',
nodes => [ nodes => [
'samlIDPMetaDataOptionsResolutionRule',
'samlIDPMetaDataOptionsNameIDFormat', 'samlIDPMetaDataOptionsNameIDFormat',
'samlIDPMetaDataOptionsForceAuthn', 'samlIDPMetaDataOptionsForceAuthn',
'samlIDPMetaDataOptionsIsPassive', 'samlIDPMetaDataOptionsIsPassive',
@ -98,6 +97,7 @@ sub cTrees {
nodes => [ nodes => [
"samlIDPMetaDataOptionsDisplayName", "samlIDPMetaDataOptionsDisplayName",
"samlIDPMetaDataOptionsIcon", "samlIDPMetaDataOptionsIcon",
'samlIDPMetaDataOptionsResolutionRule',
"samlIDPMetaDataOptionsSortNumber" "samlIDPMetaDataOptionsSortNumber"
] ]
} }
@ -186,6 +186,7 @@ sub cTrees {
nodes => [ nodes => [
'oidcOPMetaDataOptionsDisplayName', 'oidcOPMetaDataOptionsDisplayName',
'oidcOPMetaDataOptionsIcon', 'oidcOPMetaDataOptionsIcon',
'oidcOPMetaDataOptionsResolutionRule',
'oidcOPMetaDataOptionsSortNumber' 'oidcOPMetaDataOptionsSortNumber'
] ]
}, },
@ -285,6 +286,7 @@ sub cTrees {
nodes => [ nodes => [
'casSrvMetaDataOptionsDisplayName', 'casSrvMetaDataOptionsDisplayName',
'casSrvMetaDataOptionsIcon', 'casSrvMetaDataOptionsIcon',
'casSrvMetaDataOptionsResolutionRule',
'casSrvMetaDataOptionsSortNumber', 'casSrvMetaDataOptionsSortNumber',
] ]
}, },

View File

@ -146,6 +146,13 @@ function templates(tpl,key) {
"id" : tpl+"s/"+key+"/"+"casSrvMetaDataOptionsIcon", "id" : tpl+"s/"+key+"/"+"casSrvMetaDataOptionsIcon",
"title" : "casSrvMetaDataOptionsIcon" "title" : "casSrvMetaDataOptionsIcon"
}, },
{
"default" : "",
"get" : tpl+"s/"+key+"/"+"casSrvMetaDataOptionsResolutionRule",
"id" : tpl+"s/"+key+"/"+"casSrvMetaDataOptionsResolutionRule",
"title" : "casSrvMetaDataOptionsResolutionRule",
"type" : "longtext"
},
{ {
"get" : tpl+"s/"+key+"/"+"casSrvMetaDataOptionsSortNumber", "get" : tpl+"s/"+key+"/"+"casSrvMetaDataOptionsSortNumber",
"id" : tpl+"s/"+key+"/"+"casSrvMetaDataOptionsSortNumber", "id" : tpl+"s/"+key+"/"+"casSrvMetaDataOptionsSortNumber",
@ -362,6 +369,13 @@ function templates(tpl,key) {
"id" : tpl+"s/"+key+"/"+"oidcOPMetaDataOptionsIcon", "id" : tpl+"s/"+key+"/"+"oidcOPMetaDataOptionsIcon",
"title" : "oidcOPMetaDataOptionsIcon" "title" : "oidcOPMetaDataOptionsIcon"
}, },
{
"default" : "",
"get" : tpl+"s/"+key+"/"+"oidcOPMetaDataOptionsResolutionRule",
"id" : tpl+"s/"+key+"/"+"oidcOPMetaDataOptionsResolutionRule",
"title" : "oidcOPMetaDataOptionsResolutionRule",
"type" : "longtext"
},
{ {
"get" : tpl+"s/"+key+"/"+"oidcOPMetaDataOptionsSortNumber", "get" : tpl+"s/"+key+"/"+"oidcOPMetaDataOptionsSortNumber",
"id" : tpl+"s/"+key+"/"+"oidcOPMetaDataOptionsSortNumber", "id" : tpl+"s/"+key+"/"+"oidcOPMetaDataOptionsSortNumber",
@ -976,13 +990,6 @@ function templates(tpl,key) {
}, },
{ {
"_nodes" : [ "_nodes" : [
{
"default" : "",
"get" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsResolutionRule",
"id" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsResolutionRule",
"title" : "samlIDPMetaDataOptionsResolutionRule",
"type" : "longtext"
},
{ {
"default" : "", "default" : "",
"get" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsNameIDFormat", "get" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsNameIDFormat",
@ -1114,6 +1121,13 @@ function templates(tpl,key) {
"id" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsIcon", "id" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsIcon",
"title" : "samlIDPMetaDataOptionsIcon" "title" : "samlIDPMetaDataOptionsIcon"
}, },
{
"default" : "",
"get" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsResolutionRule",
"id" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsResolutionRule",
"title" : "samlIDPMetaDataOptionsResolutionRule",
"type" : "longtext"
},
{ {
"get" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsSortNumber", "get" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsSortNumber",
"id" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsSortNumber", "id" : tpl+"s/"+key+"/"+"samlIDPMetaDataOptionsSortNumber",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"مسارالأيقونة", "casSrvMetaDataOptionsIcon":"مسارالأيقونة",
"casSrvMetaDataOptionsProxiedServices":"خدمات البروكسي", "casSrvMetaDataOptionsProxiedServices":"خدمات البروكسي",
"casSrvMetaDataOptionsRenew":"تجديد إثبات الهوية", "casSrvMetaDataOptionsRenew":"تجديد إثبات الهوية",
"casSrvMetaDataOptionsResolutionRule":"حل القاعدة",
"casSrvMetaDataOptionsSortNumber":"Order", "casSrvMetaDataOptionsSortNumber":"Order",
"casSrvMetaDataOptionsUrl":" يو أر ل الخادم", "casSrvMetaDataOptionsUrl":" يو أر ل الخادم",
"casSrvName":"اسم خادم كاس", "casSrvName":"اسم خادم كاس",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"الحد الأقصى للعمر", "oidcOPMetaDataOptionsMaxAge":"الحد الأقصى للعمر",
"oidcOPMetaDataOptionsPrompt":"عاجل", "oidcOPMetaDataOptionsPrompt":"عاجل",
"oidcOPMetaDataOptionsProtocol":"بروتوكول", "oidcOPMetaDataOptionsProtocol":"بروتوكول",
"oidcOPMetaDataOptionsResolutionRule":"حل القاعدة",
"oidcOPMetaDataOptionsScope":"نطاق", "oidcOPMetaDataOptionsScope":"نطاق",
"oidcOPMetaDataOptionsSortNumber":"Order", "oidcOPMetaDataOptionsSortNumber":"Order",
"oidcOPMetaDataOptionsStoreIDToken":"مخزن تعريف التوكن", "oidcOPMetaDataOptionsStoreIDToken":"مخزن تعريف التوكن",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"Icon path", "casSrvMetaDataOptionsIcon":"Icon path",
"casSrvMetaDataOptionsProxiedServices":"Proxied services", "casSrvMetaDataOptionsProxiedServices":"Proxied services",
"casSrvMetaDataOptionsRenew":"Renew authentication", "casSrvMetaDataOptionsRenew":"Renew authentication",
"casSrvMetaDataOptionsResolutionRule":"Resolution rule",
"casSrvMetaDataOptionsSortNumber":"Order", "casSrvMetaDataOptionsSortNumber":"Order",
"casSrvMetaDataOptionsUrl":"Server URL", "casSrvMetaDataOptionsUrl":"Server URL",
"casSrvName":"CAS Server Name", "casSrvName":"CAS Server Name",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"Max age", "oidcOPMetaDataOptionsMaxAge":"Max age",
"oidcOPMetaDataOptionsPrompt":"Prompt", "oidcOPMetaDataOptionsPrompt":"Prompt",
"oidcOPMetaDataOptionsProtocol":"Protocol", "oidcOPMetaDataOptionsProtocol":"Protocol",
"oidcOPMetaDataOptionsResolutionRule":"Resolution rule",
"oidcOPMetaDataOptionsScope":"Scope", "oidcOPMetaDataOptionsScope":"Scope",
"oidcOPMetaDataOptionsSortNumber":"Order", "oidcOPMetaDataOptionsSortNumber":"Order",
"oidcOPMetaDataOptionsStoreIDToken":"Store ID Token", "oidcOPMetaDataOptionsStoreIDToken":"Store ID Token",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"Icon path", "casSrvMetaDataOptionsIcon":"Icon path",
"casSrvMetaDataOptionsProxiedServices":"Servicios proxificados", "casSrvMetaDataOptionsProxiedServices":"Servicios proxificados",
"casSrvMetaDataOptionsRenew":"Renovar autentificación", "casSrvMetaDataOptionsRenew":"Renovar autentificación",
"casSrvMetaDataOptionsResolutionRule":"Resolution rule",
"casSrvMetaDataOptionsSortNumber":"Orden", "casSrvMetaDataOptionsSortNumber":"Orden",
"casSrvMetaDataOptionsUrl":"URL de servicio", "casSrvMetaDataOptionsUrl":"URL de servicio",
"casSrvName":"Nombre de servidor CAS", "casSrvName":"Nombre de servidor CAS",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"Max age", "oidcOPMetaDataOptionsMaxAge":"Max age",
"oidcOPMetaDataOptionsPrompt":"Prompt", "oidcOPMetaDataOptionsPrompt":"Prompt",
"oidcOPMetaDataOptionsProtocol":"Protocolo", "oidcOPMetaDataOptionsProtocol":"Protocolo",
"oidcOPMetaDataOptionsResolutionRule":"Resolution rule",
"oidcOPMetaDataOptionsScope":"Ámbito", "oidcOPMetaDataOptionsScope":"Ámbito",
"oidcOPMetaDataOptionsSortNumber":"Orden", "oidcOPMetaDataOptionsSortNumber":"Orden",
"oidcOPMetaDataOptionsStoreIDToken":"Guardar token ID", "oidcOPMetaDataOptionsStoreIDToken":"Guardar token ID",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"Chemin de l'icône", "casSrvMetaDataOptionsIcon":"Chemin de l'icône",
"casSrvMetaDataOptionsProxiedServices":"Services mandatés", "casSrvMetaDataOptionsProxiedServices":"Services mandatés",
"casSrvMetaDataOptionsRenew":"Renouveler l'authentification", "casSrvMetaDataOptionsRenew":"Renouveler l'authentification",
"casSrvMetaDataOptionsResolutionRule":"Règle de résolution",
"casSrvMetaDataOptionsSortNumber":"Ordre", "casSrvMetaDataOptionsSortNumber":"Ordre",
"casSrvMetaDataOptionsUrl":"URL du serveur", "casSrvMetaDataOptionsUrl":"URL du serveur",
"casSrvName":"Nom du serveur CAS", "casSrvName":"Nom du serveur CAS",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"Age maximum", "oidcOPMetaDataOptionsMaxAge":"Age maximum",
"oidcOPMetaDataOptionsPrompt":"Interaction", "oidcOPMetaDataOptionsPrompt":"Interaction",
"oidcOPMetaDataOptionsProtocol":"Protocole", "oidcOPMetaDataOptionsProtocol":"Protocole",
"oidcOPMetaDataOptionsResolutionRule":"Règle de résolution",
"oidcOPMetaDataOptionsScope":"Scope", "oidcOPMetaDataOptionsScope":"Scope",
"oidcOPMetaDataOptionsSortNumber":"Ordre", "oidcOPMetaDataOptionsSortNumber":"Ordre",
"oidcOPMetaDataOptionsStoreIDToken":"Conserver le jeton d'identité", "oidcOPMetaDataOptionsStoreIDToken":"Conserver le jeton d'identité",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"נתיב לסמל", "casSrvMetaDataOptionsIcon":"נתיב לסמל",
"casSrvMetaDataOptionsProxiedServices":"שירותים מתווכים", "casSrvMetaDataOptionsProxiedServices":"שירותים מתווכים",
"casSrvMetaDataOptionsRenew":"חידוש אימות", "casSrvMetaDataOptionsRenew":"חידוש אימות",
"casSrvMetaDataOptionsResolutionRule":"Resolution rule",
"casSrvMetaDataOptionsSortNumber":"סדר", "casSrvMetaDataOptionsSortNumber":"סדר",
"casSrvMetaDataOptionsUrl":"כתובת שרת", "casSrvMetaDataOptionsUrl":"כתובת שרת",
"casSrvName":"CAS Server Name", "casSrvName":"CAS Server Name",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"גיל מרבי", "oidcOPMetaDataOptionsMaxAge":"גיל מרבי",
"oidcOPMetaDataOptionsPrompt":"Prompt", "oidcOPMetaDataOptionsPrompt":"Prompt",
"oidcOPMetaDataOptionsProtocol":"פרוטוקול", "oidcOPMetaDataOptionsProtocol":"פרוטוקול",
"oidcOPMetaDataOptionsResolutionRule":"Resolution rule",
"oidcOPMetaDataOptionsScope":"היקף", "oidcOPMetaDataOptionsScope":"היקף",
"oidcOPMetaDataOptionsSortNumber":"סדר", "oidcOPMetaDataOptionsSortNumber":"סדר",
"oidcOPMetaDataOptionsStoreIDToken":"Store ID Token", "oidcOPMetaDataOptionsStoreIDToken":"Store ID Token",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"Path icona", "casSrvMetaDataOptionsIcon":"Path icona",
"casSrvMetaDataOptionsProxiedServices":"Servizi Proxied", "casSrvMetaDataOptionsProxiedServices":"Servizi Proxied",
"casSrvMetaDataOptionsRenew":"Rinnova l'autenticazione", "casSrvMetaDataOptionsRenew":"Rinnova l'autenticazione",
"casSrvMetaDataOptionsResolutionRule":"Regola di risoluzione",
"casSrvMetaDataOptionsSortNumber":"Ordine", "casSrvMetaDataOptionsSortNumber":"Ordine",
"casSrvMetaDataOptionsUrl":"URL del server", "casSrvMetaDataOptionsUrl":"URL del server",
"casSrvName":"NOme del Server CAS", "casSrvName":"NOme del Server CAS",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"Età massima", "oidcOPMetaDataOptionsMaxAge":"Età massima",
"oidcOPMetaDataOptionsPrompt":"Richiesta", "oidcOPMetaDataOptionsPrompt":"Richiesta",
"oidcOPMetaDataOptionsProtocol":"Protocollo", "oidcOPMetaDataOptionsProtocol":"Protocollo",
"oidcOPMetaDataOptionsResolutionRule":"Regola di risoluzione",
"oidcOPMetaDataOptionsScope":"Scopo", "oidcOPMetaDataOptionsScope":"Scopo",
"oidcOPMetaDataOptionsSortNumber":"Ordine", "oidcOPMetaDataOptionsSortNumber":"Ordine",
"oidcOPMetaDataOptionsStoreIDToken":"Immagazzina ID Token", "oidcOPMetaDataOptionsStoreIDToken":"Immagazzina ID Token",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"Ścieżka ikony", "casSrvMetaDataOptionsIcon":"Ścieżka ikony",
"casSrvMetaDataOptionsProxiedServices":"Usługi proxy", "casSrvMetaDataOptionsProxiedServices":"Usługi proxy",
"casSrvMetaDataOptionsRenew":"Odnów uwierzytelnianie", "casSrvMetaDataOptionsRenew":"Odnów uwierzytelnianie",
"casSrvMetaDataOptionsResolutionRule":"Reguła rozstrzygania",
"casSrvMetaDataOptionsSortNumber":"Kolejność", "casSrvMetaDataOptionsSortNumber":"Kolejność",
"casSrvMetaDataOptionsUrl":"URL serwera", "casSrvMetaDataOptionsUrl":"URL serwera",
"casSrvName":"Nazwa serwera CAS", "casSrvName":"Nazwa serwera CAS",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"Maksymalny czas ważności", "oidcOPMetaDataOptionsMaxAge":"Maksymalny czas ważności",
"oidcOPMetaDataOptionsPrompt":"Prompt", "oidcOPMetaDataOptionsPrompt":"Prompt",
"oidcOPMetaDataOptionsProtocol":"Protokół", "oidcOPMetaDataOptionsProtocol":"Protokół",
"oidcOPMetaDataOptionsResolutionRule":"Reguła rozstrzygania",
"oidcOPMetaDataOptionsScope":"Zakres", "oidcOPMetaDataOptionsScope":"Zakres",
"oidcOPMetaDataOptionsSortNumber":"Kolejność", "oidcOPMetaDataOptionsSortNumber":"Kolejność",
"oidcOPMetaDataOptionsStoreIDToken":"Przechowuj token identyfikacyjny", "oidcOPMetaDataOptionsStoreIDToken":"Przechowuj token identyfikacyjny",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"İkon yolu", "casSrvMetaDataOptionsIcon":"İkon yolu",
"casSrvMetaDataOptionsProxiedServices":"Vekil sunucu servisleri", "casSrvMetaDataOptionsProxiedServices":"Vekil sunucu servisleri",
"casSrvMetaDataOptionsRenew":"Kimlik doğrulamayı yenile", "casSrvMetaDataOptionsRenew":"Kimlik doğrulamayı yenile",
"casSrvMetaDataOptionsResolutionRule":"Çözünürlük kuralı",
"casSrvMetaDataOptionsSortNumber":"Sıra", "casSrvMetaDataOptionsSortNumber":"Sıra",
"casSrvMetaDataOptionsUrl":"Sunucu URL'si", "casSrvMetaDataOptionsUrl":"Sunucu URL'si",
"casSrvName":"CAS Sunucu Adı", "casSrvName":"CAS Sunucu Adı",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"Maksimum ömür", "oidcOPMetaDataOptionsMaxAge":"Maksimum ömür",
"oidcOPMetaDataOptionsPrompt":"İstem", "oidcOPMetaDataOptionsPrompt":"İstem",
"oidcOPMetaDataOptionsProtocol":"Protokol", "oidcOPMetaDataOptionsProtocol":"Protokol",
"oidcOPMetaDataOptionsResolutionRule":"Çözünürlük kuralı",
"oidcOPMetaDataOptionsScope":"Kapsam", "oidcOPMetaDataOptionsScope":"Kapsam",
"oidcOPMetaDataOptionsSortNumber":"Sıra", "oidcOPMetaDataOptionsSortNumber":"Sıra",
"oidcOPMetaDataOptionsStoreIDToken":"ID Jetonu Sakla", "oidcOPMetaDataOptionsStoreIDToken":"ID Jetonu Sakla",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"Đường dẫn Icon", "casSrvMetaDataOptionsIcon":"Đường dẫn Icon",
"casSrvMetaDataOptionsProxiedServices":"Dịch vụ proxy", "casSrvMetaDataOptionsProxiedServices":"Dịch vụ proxy",
"casSrvMetaDataOptionsRenew":"Gia hạn chứng thực", "casSrvMetaDataOptionsRenew":"Gia hạn chứng thực",
"casSrvMetaDataOptionsResolutionRule":"Quy tắc phân giải ",
"casSrvMetaDataOptionsSortNumber":"Order", "casSrvMetaDataOptionsSortNumber":"Order",
"casSrvMetaDataOptionsUrl":"URL máy chủ", "casSrvMetaDataOptionsUrl":"URL máy chủ",
"casSrvName":"Tên máy chủ CAS", "casSrvName":"Tên máy chủ CAS",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"Thời hạn tối đa", "oidcOPMetaDataOptionsMaxAge":"Thời hạn tối đa",
"oidcOPMetaDataOptionsPrompt":"Nhắc nhở", "oidcOPMetaDataOptionsPrompt":"Nhắc nhở",
"oidcOPMetaDataOptionsProtocol":"Giao thức", "oidcOPMetaDataOptionsProtocol":"Giao thức",
"oidcOPMetaDataOptionsResolutionRule":"Quy tắc phân giải ",
"oidcOPMetaDataOptionsScope":"Phạm vi", "oidcOPMetaDataOptionsScope":"Phạm vi",
"oidcOPMetaDataOptionsSortNumber":"Order", "oidcOPMetaDataOptionsSortNumber":"Order",
"oidcOPMetaDataOptionsStoreIDToken":"Mã thông báo Cửa hàng", "oidcOPMetaDataOptionsStoreIDToken":"Mã thông báo Cửa hàng",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"图标路径", "casSrvMetaDataOptionsIcon":"图标路径",
"casSrvMetaDataOptionsProxiedServices":"代理服务", "casSrvMetaDataOptionsProxiedServices":"代理服务",
"casSrvMetaDataOptionsRenew":"更新驗證", "casSrvMetaDataOptionsRenew":"更新驗證",
"casSrvMetaDataOptionsResolutionRule":"解析規則",
"casSrvMetaDataOptionsSortNumber":"順序", "casSrvMetaDataOptionsSortNumber":"順序",
"casSrvMetaDataOptionsUrl":"服务器 URL", "casSrvMetaDataOptionsUrl":"服务器 URL",
"casSrvName":"CAS 服务器名称", "casSrvName":"CAS 服务器名称",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"最大時間", "oidcOPMetaDataOptionsMaxAge":"最大時間",
"oidcOPMetaDataOptionsPrompt":"提示", "oidcOPMetaDataOptionsPrompt":"提示",
"oidcOPMetaDataOptionsProtocol":"協定", "oidcOPMetaDataOptionsProtocol":"協定",
"oidcOPMetaDataOptionsResolutionRule":"解析規則",
"oidcOPMetaDataOptionsScope":"範圍", "oidcOPMetaDataOptionsScope":"範圍",
"oidcOPMetaDataOptionsSortNumber":"順序", "oidcOPMetaDataOptionsSortNumber":"順序",
"oidcOPMetaDataOptionsStoreIDToken":"儲存 ID 權杖", "oidcOPMetaDataOptionsStoreIDToken":"儲存 ID 權杖",

View File

@ -161,6 +161,7 @@
"casSrvMetaDataOptionsIcon":"圖示路徑", "casSrvMetaDataOptionsIcon":"圖示路徑",
"casSrvMetaDataOptionsProxiedServices":"已代理的服務", "casSrvMetaDataOptionsProxiedServices":"已代理的服務",
"casSrvMetaDataOptionsRenew":"更新驗證", "casSrvMetaDataOptionsRenew":"更新驗證",
"casSrvMetaDataOptionsResolutionRule":"解析規則",
"casSrvMetaDataOptionsSortNumber":"順序", "casSrvMetaDataOptionsSortNumber":"順序",
"casSrvMetaDataOptionsUrl":"伺服器 URL", "casSrvMetaDataOptionsUrl":"伺服器 URL",
"casSrvName":"CAS 伺服器名稱", "casSrvName":"CAS 伺服器名稱",
@ -652,6 +653,7 @@
"oidcOPMetaDataOptionsMaxAge":"最大時間", "oidcOPMetaDataOptionsMaxAge":"最大時間",
"oidcOPMetaDataOptionsPrompt":"提示", "oidcOPMetaDataOptionsPrompt":"提示",
"oidcOPMetaDataOptionsProtocol":"協定", "oidcOPMetaDataOptionsProtocol":"協定",
"oidcOPMetaDataOptionsResolutionRule":"解析規則",
"oidcOPMetaDataOptionsScope":"範圍", "oidcOPMetaDataOptionsScope":"範圍",
"oidcOPMetaDataOptionsSortNumber":"順序", "oidcOPMetaDataOptionsSortNumber":"順序",
"oidcOPMetaDataOptionsStoreIDToken":"儲存 ID 權杖", "oidcOPMetaDataOptionsStoreIDToken":"儲存 ID 權杖",

View File

@ -561,8 +561,9 @@ t/30-Auth-and-issuer-SAML-POST.t
t/30-Auth-and-issuer-SAML-Redirect-IdP-initiated.t t/30-Auth-and-issuer-SAML-Redirect-IdP-initiated.t
t/30-Auth-and-issuer-SAML-Redirect-MultipleSP-Missing-SLO.t t/30-Auth-and-issuer-SAML-Redirect-MultipleSP-Missing-SLO.t
t/30-Auth-and-issuer-SAML-Redirect-MultipleSP.t t/30-Auth-and-issuer-SAML-Redirect-MultipleSP.t
t/30-Auth-and-issuer-SAML-Redirect-With-Info.t
t/30-Auth-and-issuer-SAML-Redirect.t t/30-Auth-and-issuer-SAML-Redirect.t
t/30-Auth-and-issuer-SAML-Redirect-With-Info.t
t/30-Auth-ResolutionRule.t
t/30-Auth-SAML-with-choice.t t/30-Auth-SAML-with-choice.t
t/30-CDC.t t/30-CDC.t
t/30-SAML-Head-to-Tail-POST.t t/30-SAML-Head-to-Tail-POST.t

View File

@ -133,14 +133,24 @@ sub extractFormInfo {
else { else {
# Server list # Try to use server resolution ruls
my $portalPath = $self->conf->{portal}; foreach ( keys %{ $self->srvRules } ) {
$portalPath =~ s#^https?://[^/]+/?#/#; my $cond = $self->srvRules->{$_} or next;
if ( $cond->( $req, $req->sessionInfo ) ) {
$self->logger->debug(
"CAS Server $_ selected from resolution rule");
$srv = $_;
last;
}
}
$req->data->{list} = $self->srvList; unless ($srv) {
$req->data->{login} = 1; # Server list
return PE_IDPCHOICE; $req->data->{list} = $self->srvList;
$req->data->{login} = 1;
return PE_IDPCHOICE;
}
} }
} }

View File

@ -249,14 +249,23 @@ sub extractFormInfo {
else { else {
# IDP list # Try to use OP resolution ruls
my $portalPath = $self->{conf}->{portal}; foreach ( keys %{ $self->opRules } ) {
$portalPath =~ s#^https?://[^/]+/?#/#; my $cond = $self->opRules->{$_} or next;
if ( $cond->( $req, $req->sessionInfo ) ) {
$self->logger->debug("OP $_ selected from resolution rule");
$op = $_;
last;
}
}
$req->data->{list} = $self->opList; unless ($op) {
$req->data->{login} = 1; # display OP list
return PE_IDPCHOICE; $req->data->{list} = $self->opList;
$req->data->{login} = 1;
return PE_IDPCHOICE;
}
} }
} }

View File

@ -26,6 +26,7 @@ has ua => (
has casSrvList => ( is => 'rw', default => sub { {} }, ); has casSrvList => ( is => 'rw', default => sub { {} }, );
has casAppList => ( is => 'rw', default => sub { {} }, ); has casAppList => ( is => 'rw', default => sub { {} }, );
has srvRules => ( is => 'rw', default => sub { {} }, );
has spRules => ( is => 'rw', default => sub { {} }, ); has spRules => ( is => 'rw', default => sub { {} }, );
has spMacros => ( is => 'rw', default => sub { {} }, ); has spMacros => ( is => 'rw', default => sub { {} }, );
@ -41,6 +42,18 @@ sub loadSrv {
return 0; return 0;
} }
$self->casSrvList( $self->conf->{casSrvMetaDataOptions} ); $self->casSrvList( $self->conf->{casSrvMetaDataOptions} );
# Set rule
foreach ( keys %{ $self->conf->{casSrvMetaDataOptions} } ) {
my $cond = $self->conf->{casSrvMetaDataOptions}->{$_}
->{casSrvMetaDataOptionsResolutionRule};
if ( length $cond ) {
my $rule_sub = $self->p->buildRule( $cond, "CAS server resolution" );
if ($rule_sub) {
$self->srvRules->{$_} = $rule_sub;
}
}
}
return 1; return 1;
} }

View File

@ -41,6 +41,7 @@ use constant OIDC_SCOPES => [qw/openid profile email address phone/];
has oidcOPList => ( is => 'rw', default => sub { {} }, ); has oidcOPList => ( is => 'rw', default => sub { {} }, );
has oidcRPList => ( is => 'rw', default => sub { {} }, ); has oidcRPList => ( is => 'rw', default => sub { {} }, );
has rpAttributes => ( is => 'rw', default => sub { {} }, ); has rpAttributes => ( is => 'rw', default => sub { {} }, );
has opRules => ( is => 'rw', default => sub { {} } );
has spRules => ( is => 'rw', default => sub { {} } ); has spRules => ( is => 'rw', default => sub { {} } );
has spMacros => ( is => 'rw', default => sub { {} } ); has spMacros => ( is => 'rw', default => sub { {} } );
has spScopeRules => ( is => 'rw', default => sub { {} } ); has spScopeRules => ( is => 'rw', default => sub { {} } );
@ -90,6 +91,20 @@ sub loadOPs {
$self->oidcOPList->{$_}->{jwks} = $self->oidcOPList->{$_}->{jwks} =
$self->decodeJSON( $self->conf->{oidcOPMetaDataJWKS}->{$_} ); $self->decodeJSON( $self->conf->{oidcOPMetaDataJWKS}->{$_} );
} }
# Set rule
foreach ( keys %{ $self->conf->{oidcOPMetaDataOptions} } ) {
my $cond = $self->conf->{oidcOPMetaDataOptions}->{$_}
->{oidcOPMetaDataOptionsResolutionRule};
if ( length $cond ) {
my $rule_sub =
$self->p->buildRule( $cond, "OIDC provider resolution" );
if ($rule_sub) {
$self->opRules->{$_} = $rule_sub;
}
}
}
return 1; return 1;
} }

View File

@ -0,0 +1,138 @@
use lib 'inc';
use Test::More;
use strict;
use IO::String;
use LWP::UserAgent;
use LWP::Protocol::PSGI;
use MIME::Base64;
use XML::LibXML;
BEGIN {
require 't/test-lib.pm';
require 't/saml-lib.pm';
}
my $debug = 'error';
my ( $issuer, $res );
my $maintests = 0;
sub testchoiceredirection {
my ( $issuer, $choice, $url ) = @_;
my $res;
ok(
$res = $issuer->_get(
'/',
query => 'lmAuth=' . $choice,
accept => 'text/html',
),
'Auth query'
);
count(1);
expectRedirection( $res, $url );
}
SKIP: {
eval "use Lasso";
if ($@) {
skip 'Lasso not found', $maintests;
}
# Initialization
ok( $issuer = issuer(), 'Issuer portal' );
count(1);
testchoiceredirection( $issuer, 'SAML1',
qr,http://auth.idp.com/saml/singleSignOn, );
testchoiceredirection( $issuer, 'SAML2',
qr,http://auth.idp2.com/saml/singleSignOn, );
testchoiceredirection( $issuer, 'OIDC1',
qr,http://auth.op.com/oauth2/authorize, );
testchoiceredirection( $issuer, 'OIDC2',
qr,http://auth.op2.com/oauth2/authorize, );
testchoiceredirection( $issuer, 'CAS1', qr,http://auth.srv.com/cas/login, );
testchoiceredirection( $issuer, 'CAS2',
qr,http://auth.srv2.com/cas/login, );
clean_sessions();
}
count($maintests);
done_testing( count() );
sub issuer {
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
domain => 'example.com',
portal => 'http://auth.example.com',
authentication => 'Choice',
userDB => 'Same',
authChoiceModules => {
'OIDC1' => 'OpenIDConnect;Null;Null',
'OIDC2' => 'OpenIDConnect;Null;Null',
'SAML1' => 'SAML;Null;Null',
'SAML2' => 'SAML;Null;Null',
'CAS1' => 'CAS;Null;Null',
'CAS2' => 'CAS;Null;Null',
},
samlIDPMetaDataOptions => {
"idp.com" => {
samlIDPMetaDataOptionsResolutionRule =>
'$_choice eq "SAML1"',
},
"idp2.com" => {
samlIDPMetaDataOptionsResolutionRule =>
'$_choice eq "SAML2"',
},
},
samlIDPMetaDataXML => {
"idp.com" => {
samlIDPMetaDataXML =>
samlIDPMetaDataXML( 'idp', 'HTTP-Redirect' )
},
"idp2.com" => {
samlIDPMetaDataXML =>
samlIDPMetaDataXML( 'idp2', 'HTTP-Redirect' )
},
},
samlServicePrivateKeyEnc => saml_key_idp_private_enc,
samlServicePrivateKeySig => saml_key_idp_private_sig,
samlServicePublicKeyEnc => saml_key_idp_public_enc,
samlServicePublicKeySig => saml_key_idp_public_sig,
casSrvMetaDataOptions => {
idp => {
casSrvMetaDataOptionsUrl => 'http://auth.srv.com/cas',
casSrvMetaDataOptionsResolutionRule =>
'$_choice eq "CAS1"',
},
idp2 => {
casSrvMetaDataOptionsUrl => 'http://auth.srv2.com/cas',
casSrvMetaDataOptionsResolutionRule =>
'$_choice eq "CAS2"',
},
},
oidcOPMetaDataOptions => {
op => {
oidcOPMetaDataOptionsClientSecret => "rpsecret",
oidcOPMetaDataOptionsResolutionRule =>
'$_choice eq "OIDC1"',
},
op2 => {
oidcOPMetaDataOptionsResolutionRule =>
'$_choice eq "OIDC2"',
},
},
oidcOPMetaDataJSON => {
op =>
'{"authorization_endpoint":"http://auth.op.com/oauth2/authorize"}',
op2 =>
'{"authorization_endpoint":"http://auth.op2.com/oauth2/authorize"}',
}
}
}
);
}