Merge branch 'v2.0'

This commit is contained in:
Yadd 2021-04-09 18:15:50 +02:00
commit 30b5b93adc
22 changed files with 107 additions and 29 deletions

View File

@ -56,7 +56,7 @@ Notes
* Your ID Token Signature Algorithm has to be RSxxx, symmetric algorithms seem broken as of Greenlight 2.7.17
* ``OAUTH2_REDIRECT`` must match the URL you use to access Greenlight. the
``auth/openid_connect/callback`` suffix must be omitted
* Greenlight will not work if your LemonLDAP::NG server is not served over HTTPS using a publically recognized certificate authority (such as Let's Encrypt)
* Greenlight requires your LemonLDAP::NG server to be served over HTTPS using a publically recognized certificate authority (such as Let's Encrypt)
.. |logo| image:: /applications/bigbluebutton-logo.png
:class: align-center

View File

@ -49,9 +49,6 @@ Then go in ``CAS Service`` to define:
- **CAS login**: the session key transmitted to CAS client as the main
identifier (CAS Principal). This setting can be overriden
per-application.
- **CAS attributes**: list of attributes that will be transmitted by
default in the validate response. Keys are the name of attribute in
the CAS response, values are the name of session key.
- **Access control policy**: define if access control should be done on
CAS service. Three options:
@ -67,6 +64,13 @@ Then go in ``CAS Service`` to define:
- **CAS session module name and options**: choose a specific module if
you do not want to mix CAS sessions and normal sessions (see
:ref:`why<samlservice-saml-sessions-module-name-and-options>`).
- **CAS attributes**: list of attributes that will be transmitted by
default in the validate response. Keys are the name of attribute in
the CAS response, values are the name of session key.
- **Use strict URL matching**: (since *2.0.12*) enforces a stricter URL
matching. By default, LemonLDAP::NG will try to find a declared CAS
Application matching the hostname of the requested application if it cannot
find a match using the full path. See :ref:`idpcas-url-matching` for details
.. tip::
@ -143,3 +147,13 @@ For example, if you declared two applications in LemonLDAP::NG with the followin
* https://cas.example.com/applications/
An application located at https://cas.example.com/applications/zone1/myapp will match the first CAS service definition
An application located at https://cas.example.com/undeclared/ will also be accepted in order to preserve the previous behavior of matching on hostnames only.
.. versionchanged:: 2.0.12
The *Strict URL matching* option now lets you decide if LemonLDAP::NG should
fall back to legacy host-based matching if it cannot find a declared service
matching an incoming service URL. In the previous example,
https://cas.example.com/undeclared/ will no longer match if strict URL
matching is enabled

View File

@ -38,16 +38,24 @@ It is recommended to use NTP to do this.
DNS
~~~
The auth.example.com must be registered in the DNS server (which is
Active Directory). The reverse DNS of auth.example.com **must** return
the portal IP.
In our experience, we have observed the following limitations when using Kerberos for web applications in an Active Directory environment
* ``auth.example.com`` must be registered in the DNS server as a ``A`` record. ``CNAME`` usually do not work
* The reverse DNS (``PTR``) for ``auth.example.com``'s IP address MUST point back to ``auth.example.com``
.. tip::
If you have a SSO cluster, you must setup a Virtual IP in
cluster and register this IP in DNS.
.. tip::
If you cannot configure the PTR record to point to the portal's hostname, it
may help to run the following command. Assuming that ``proxy.example.com`` is
the PTR record of the portal's IP address ::
setspn -s HTTP/proxy.example.com keytab-account
SSL
~~~

View File

@ -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)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:DevOps(?:Download)?|State|User|XSS)|rowdsec|da)|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|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|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)|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(?:Download)?|State|User|XSS)|rowdsec|da)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:G(?:roup(?:DecodeSearchedValu|Recursiv)|etUserBeforePasswordChang)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|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|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' );

View File

@ -811,6 +811,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'casStorageOptions' => {
'type' => 'keyTextContainer'
},
'casStrictMatching' => {
'default' => 0,
'type' => 'bool'
},
'cda' => {
'default' => 0,
'type' => 'bool'

View File

@ -2431,6 +2431,11 @@ sub attributes {
type => 'keyTextContainer',
documentation => 'Apache::Session module parameters',
},
casStrictMatching => {
default => 0,
type => 'bool',
documentation => 'Disable host-based matching of CAS services',
},
issuerDBCASActivation => {
default => 0,
type => 'bool',

View File

@ -1364,6 +1364,7 @@ sub tree {
'casStorage',
'casStorageOptions',
'casAttributes',
'casStrictMatching',
]
},

View File

@ -171,6 +171,7 @@
"casSrvName":"اسم خادم كاس",
"casStorage":"اسم وحدة جلسات كاس",
"casStorageOptions":" خيارات وحدة جلسات كاس",
"casStrictMatching":"Use strict URL matching",
"categoryName":"اسم الفئة",
"cda":"نطاقات متعددة",
"certificateMailContent":"محتوى البريد",
@ -1088,7 +1089,7 @@
"ssoSessions":"جلسات السسو",
"stateCheck":"State Check",
"stayConnect":"الاتصالات المستمرة",
"stayConnected":"Activation",
"stayConnected":"تفعيل",
"stayConnectedCookieName":"اسم ملف تعريف الارتباط",
"stayConnectedTimeout":"Expiration time",
"storePassword":"تخزين كلمة مرور المستخدم في بيانات الجلسة",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"خدمة أل يو أر ل",
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
"zeroConfExplanations":"لا يحتوي الخادم على إعدادات. استخدام قالب لحفظ الأول"
}
}

View File

@ -171,6 +171,7 @@
"casSrvName":"CAS Servername",
"casStorage":"CAS sessions module name",
"casStorageOptions":"CAS sessions module options",
"casStrictMatching":"Use strict URL matching",
"categoryName":"Category name",
"cda":"Mehrere Domains",
"certificateMailContent":"Mail content",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"Service URL",
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
"zeroConfExplanations":"Server has no configuration. Use template to save the first."
}
}

View File

@ -171,6 +171,7 @@
"casSrvName":"CAS Server Name",
"casStorage":"CAS sessions module name",
"casStorageOptions":"CAS sessions module options",
"casStrictMatching":"Use strict URL matching",
"categoryName":"Category name",
"cda":"Multiple domains",
"certificateMailContent":"Mail content",

View File

@ -171,6 +171,7 @@
"casSrvName":"Nombre de servidor CAS",
"casStorage":"CAS sessions module name",
"casStorageOptions":"CAS sessions module options",
"casStrictMatching":"Use strict URL matching",
"categoryName":"Nombre de categoría",
"cda":"Dominios múltiples",
"certificateMailContent":"Contenido de correo",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"Service URL",
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
"zeroConfExplanations":"Server has no configuration. Use template to save the first."
}
}

View File

@ -171,6 +171,7 @@
"casSrvName":"Nom du serveur CAS",
"casStorage":"Nom du module des sessions CAS",
"casStorageOptions":"Options du module des sessions CAS",
"casStrictMatching":"Filtrage strict des URL",
"categoryName":"Nom de la catégorie",
"cda":"Domaines multiples",
"certificateMailContent":"Contenu du mail",

View File

@ -171,6 +171,7 @@
"casSrvName":"NOme del Server CAS",
"casStorage":"Nome del modulo sessioni CAS",
"casStorageOptions":"Opzioni del modulo sessioni CAS",
"casStrictMatching":"Use strict URL matching",
"categoryName":"Nome della categoria",
"cda":"Domini multipli",
"certificateMailContent":"Contenuto della mail",
@ -374,7 +375,7 @@
"githubClientID":"Client ID",
"githubClientSecret":"Client secret",
"githubParams":"GitHub Parameters",
"githubScope":"Scope",
"githubScope":"Scopo",
"githubUserField":"Field containing user identifier",
"globalLogout":"Global logout",
"globalLogoutCustomParam":"Custom parameter",
@ -1088,7 +1089,7 @@
"ssoSessions":"Sessioni SSO",
"stateCheck":"Controllo dello stato",
"stayConnect":"Connessioni persistenti",
"stayConnected":"Activation",
"stayConnected":"Attivazione",
"stayConnectedCookieName":"Nome del cookie",
"stayConnectedTimeout":"Expiration time",
"storePassword":"Memorizzare la password dell'utente nei dati di sessione",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"URL del servizio",
"yubikey2fUserCanRemoveKey":"Autorizza l'utente a rimuovere la Yubikey",
"zeroConfExplanations":"Il server non ha alcuna configurazione. Utilizza il modello per salvare il primo."
}
}

View File

@ -171,6 +171,7 @@
"casSrvName":"Nazwa serwera CAS",
"casStorage":"Nazwa modułu sesji CAS",
"casStorageOptions":"Opcje modułu sesji CAS",
"casStrictMatching":"Use strict URL matching",
"categoryName":"Nazwa Kategorii",
"cda":"Wiele domen",
"certificateMailContent":"Treść wiadomości",
@ -185,7 +186,7 @@
"certificateResetByMailValidityDelay":"Minimalny czas do wygaśnięcia",
"cfgLog":"Podsumowanie",
"cfgVersion":"Wersja konfiguracji",
"checkDevOps":"Activation",
"checkDevOps":"Aktywacja",
"checkDevOpsDownload":"Download file",
"checkState":"Aktywacja",
"checkStateSecret":"Współdzielony sekret",
@ -246,9 +247,9 @@
"corsMax_Age":"Access-Control-Max-Age",
"create":"Stwórz",
"crossOrigineResourceSharing":"Udostępnianie zasobów między źródłami",
"crowdsec":"Activation",
"crowdsecAction":"Action",
"crowdsecKey":"API key",
"crowdsec":"Aktywacja",
"crowdsecAction":"Akcja",
"crowdsecKey":"Klucz API",
"crowdsecUrl":"Base URL of local API",
"cspConnect":"Miejsca docelowe Ajax",
"cspDefault":"Domyślna wartość",
@ -1079,7 +1080,7 @@
"slaveParams":"Parametry slave",
"slaveUserHeader":"Nagłówek logowania użytkownika",
"soapConfigServer":"Configuration server",
"soapServices":"SOAP services",
"soapServices":"Usługa SOAP",
"soapSessionServer":"Session server",
"specialRule":"Reguła specjalna",
"sslByAjax":"Użyj żądania Ajax",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"URL usługi",
"yubikey2fUserCanRemoveKey":"Pozwól użytkownikowi usunąć Yubikey",
"zeroConfExplanations":"Serwer nie ma konfiguracji. Użyj szablonu, aby zapisać pierwszy."
}
}

View File

@ -171,6 +171,7 @@
"casSrvName":"CAS Sunucu Adı",
"casStorage":"CAS oturumları modül adı",
"casStorageOptions":"CAS oturumları modül seçenekleri",
"casStrictMatching":"Use strict URL matching",
"categoryName":"Kategori ismi",
"cda":"Çoklu alan adları",
"certificateMailContent":"E-posta içeriği",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"Servis URL'si",
"yubikey2fUserCanRemoveKey":"Yubikey'i kaldırmak için kullanıcıya izin ver",
"zeroConfExplanations":"Sunucunun yapılandırması yok. Şimdi bir tane kaydetmek için şablonu kullanın."
}
}

View File

@ -171,6 +171,7 @@
"casSrvName":"Tên máy chủ CAS",
"casStorage":"Tên mô-đun phiên CAS",
"casStorageOptions":"Các tùy chọn mô-đun phiên CAS",
"casStrictMatching":"Use strict URL matching",
"categoryName":"Tên thể loại",
"cda":"Nhiều tên miền",
"certificateMailContent":"Nội dung thư",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"Dịch vụ URL",
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
"zeroConfExplanations":"Máy chủ không có cấu hình. Sử dụng mẫu để lưu đầu tiên. "
}
}

View File

@ -171,6 +171,7 @@
"casSrvName":"CAS 服务器名称",
"casStorage":"CAS 会话模块名称",
"casStorageOptions":"CAS 会话模块选项",
"casStrictMatching":"Use strict URL matching",
"categoryName":"分类名称",
"cda":"Multiple domains",
"certificateMailContent":"Mail content",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"Service URL",
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
"zeroConfExplanations":"Server has no configuration. Use template to save the first."
}
}

View File

@ -171,6 +171,7 @@
"casSrvName":"CAS 伺服器名稱",
"casStorage":"CAS 工作階段模組名稱",
"casStorageOptions":"CAS 工作階段模組選項",
"casStrictMatching":"Use strict URL matching",
"categoryName":"分類名稱",
"cda":"多域名",
"certificateMailContent":"郵件內容",
@ -1211,4 +1212,4 @@
"yubikey2fUrl":"服務 URL",
"yubikey2fUserCanRemoveKey":"允許使用者移除 Yubikey",
"zeroConfExplanations":"伺服器未設定。使用飯本來儲存第一個。"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -562,8 +562,10 @@ sub getCasApp {
}
}
# Try to match host
$hostnameConfKey = $app if ( $hostname eq $candidateHost );
# Try to match host, only if strict matching is disabled
unless ( $self->conf->{casStrictMatching} ) {
$hostnameConfKey = $app if ( $hostname eq $candidateHost );
}
}
# Application found by prefix has priority

View File

@ -56,10 +56,42 @@ ok(
count(1);
expectRedirection( $res, qr#^http://auth.other.com/srv2\?(ticket=[^&]+)$# );
# New test with StrictMatching
ok( $issuer = issuer(1), 'Issuer portal' );
count(1);
# Service 1, will be matched by URI
ok(
$res = $issuer->_get(
'/cas/login',
query => 'service=http://auth.sp.com/srv1/index.php',
accept => 'text/html',
cookie => "lemonldap=$id",
),
'Query CAS server'
);
count(1);
expectRedirection( $res,
qr#^http://auth.sp.com/srv1/index.php\?(ticket=[^&]+)$# );
# Service 2, will now fail
ok(
$res = $issuer->_get(
'/cas/login',
query => 'service=http://auth.other.com/srv2',
accept => 'text/html',
cookie => "lemonldap=$id",
),
'Query CAS server'
);
count(1);
expectPortalError( $res, 68 );
clean_sessions();
done_testing( count() );
sub issuer {
my ($strict) = @_;
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
@ -69,6 +101,7 @@ sub issuer {
userDB => 'Same',
issuerDBCASActivation => 1,
casAttr => 'uid',
casStrictMatching => $strict,
casAppMetaDataOptions => {
sp1 => {
casAppMetaDataOptionsService =>