Hello Yan,

no, this is not something specific to Groovy. You can also have as return 
statements as needed.

The problem here was in wrongly expecting that "return ..." inside 
"cc.each" exits the whole "run" method (even if it did, the script's 
functionality would then depend on whether there could be multiple items in 
"cc" and on their order). One of the solutions is to use a simple "for" 
loop instead, or a method like "any": *if (cc.any { it.matches('23K65.+') 
}) {* ...

Best regards
Petr
On Thursday, 4 December 2025 at 22:01:32 UTC+1 Yan Zhou wrote:

> Hello, 
>
> this is interesting, it is happening to me with CAS 7.3.1 overlay,  is 
> this something specific to Groovy?  Only one return statement allowed in 
> script?
>
> thx!
>
> On Monday, October 19, 2020 at 5:31:19 AM UTC-4 Otto Myyrä wrote:
>
>> Ok, found the problem. It started working after removing all the 
>> different return something lines within the if clauses in the groovy script.
>>
>> Replaced all returns within the code with a temporary variable and 
>> returned that variable at the end of the script. Works now.
>>
>> BR,
>> Otto Myyrä
>> On Monday, October 19, 2020 at 9:55:53 AM UTC+3 Otto Myyrä wrote:
>>
>>> Hi.
>>>
>>> Thank you for your suggestion. Unfortunately it seems we won't be able 
>>> to use it since we are checking for SPnego in the groovy script and 
>>> globalPrincipalAttributePredicate doesn't seem to convey authentication 
>>> context to the groovy script, therefore making it impossible to base the 
>>> mfa triggering logic on the existing/not existing SPnego auth.
>>>
>>> Running cas with debug level logging tells us this after the 
>>> groovy-trigger returns "mfa-duo" for cas:
>>> 2020-10-16 14:47:49,276 DEBUG 
>>> [org.apereo.cas.web.flow.resolver.impl.DefaultCasDelegatingWebflowEventResolver]
>>>  
>>> - <Transition definition cannot be found for event mfa-duo>
>>> org.apereo.cas.authentication.AuthenticationException: Transition 
>>> definition cannot be found for event mfa-duo
>>>         at 
>>> org.apereo.cas.authentication.MultifactorAuthenticationUtils.lambda$validateEventIdForMatchingTransitionInContext$1(MultifactorAuthenticationUtils.java:74)
>>>  
>>> ~[cas-server-core-authentication-mfa-api-6.1.7.1.jar!/:6.1.7.1]
>>>
>>> Are we just missing something obvious?
>>>
>>> BR,
>>> Otto Myyrä
>>>
>>> On Friday, October 16, 2020 at 12:46:20 AM UTC+3 [email protected] 
>>> wrote:
>>>
>>>> Here's one that we managed to get working, you can try similar settings 
>>>> to see if they help
>>>>
>>>>
>>>> cas.authn.mfa.duo[0].id=mfa-duo
>>>>
>>>> cas.authn.mfa.globalPrincipalAttributePredicate=file:/etc/cas/attributeCollection/DetermineMFA.groovy
>>>> cas.authn.mfa.duo[0].rank=0
>>>> cas.authn.mfa.duo[0].duoApplicationKey=${key_duo_app}
>>>> cas.authn.mfa.duo[0].duoIntegrationKey=${key_duo_integration}
>>>> cas.authn.mfa.duo[0].duoApiHost=${duo_api_host}
>>>> cas.authn.mfa.duo[0].duoSecretKey=${key_duo}
>>>>
>>>>
>>>>
>>>> On Tuesday, October 13, 2020 at 3:05:48 AM UTC-6 Otto Myyrä wrote:
>>>>
>>>>> Sorry, realized I forgot to include version information. We are 
>>>>> running CAS 6.1.7.1.
>>>>>
>>>>> On Tuesday, October 13, 2020 at 12:02:48 PM UTC+3 Otto Myyrä wrote:
>>>>>
>>>>>> Hello.
>>>>>>
>>>>>> We are having trouble actually triggering the mfa-authentication with 
>>>>>> a groovy trigger script despite the trigger script running (and logging 
>>>>>> what it's doing) seemingly just fine.
>>>>>>
>>>>>> We authenticate from ldap and also support spnego authentication and 
>>>>>> then trigger mfa with a groovy trigger if spnego isn't in use. The 
>>>>>> groovy 
>>>>>> script runs and does what it's supposed to do and then returns what it's 
>>>>>> (apparently) supposed to return but the mfa process does not trigger 
>>>>>> after 
>>>>>> that regardless.
>>>>>>
>>>>>> If we activate mfa globally based on a principal attribute instead of 
>>>>>> a groovy trigger, then the mfa works as it should. If we try to do it 
>>>>>> with 
>>>>>> the groovy script it won't activate. Would any of you have any idea what 
>>>>>> we're doing wrong?
>>>>>>
>>>>>> Here's the mfa configuration in cas.properties:
>>>>>> ##
>>>>>> #DUO MFA provider
>>>>>> cas.authn.mfa.duo[0].duoSecretKey=[redacted]
>>>>>> cas.authn.mfa.duo[0].rank=1
>>>>>> cas.authn.mfa.duo[0].duoApplicationKey=[redacted]
>>>>>> cas.authn.mfa.duo[0].duoIntegrationKey=[redacted]
>>>>>> cas.authn.mfa.duo[0].duoApiHost=[redacted]
>>>>>> cas.authn.mfa.duo[0].trustedDeviceEnabled=false
>>>>>> cas.authn.mfa.duo[0].id=mfa-duo
>>>>>> cas.authn.mfa.duo[0].registrationUrl=https://[redacted]
>>>>>> cas.authn.mfa.duo[0].name=Login (CAS)
>>>>>> cas.authn.mfa.duo[0].order=1
>>>>>>
>>>>>> cas.authn.mfa.groovyScript=file:/etc/cas/mfaGroovyTrigger.groovy
>>>>>> cas.authn.mfa.provider-selection-enabled=true
>>>>>>
>>>>>>
>>>>>> #cas.authn.mfa.globalPrincipalAttributeNameTriggers=LGUserType,Company,CostCenter
>>>>>> #cas.authn.mfa.globalPrincipalAttributeValueRegex=23K65.*
>>>>>> #cas.authn.mfa.globalPrincipalAttributeValueRegex=donotmatch
>>>>>>
>>>>>> (the commented out lines are the tests with the principal attribute, 
>>>>>> those work)
>>>>>>
>>>>>>
>>>>>> This is the groovy trigger script:
>>>>>>
>>>>>> import java.util.*
>>>>>>
>>>>>> class MFACustomTrigger {
>>>>>>         def String run(final Object... args) {
>>>>>>                 def service = args[0]
>>>>>>                 def registeredService = args[1]
>>>>>>                 def authentication = args[2]
>>>>>>                 def httpRequest = args[3]
>>>>>>                 def logger = args[4]
>>>>>>
>>>>>>                 logger.info("Evaluating authentication attributes 
>>>>>> [{}]", authentication.attributes)
>>>>>>                 logger.info("Evaluating principal attributes [{}]", 
>>>>>> authentication.principal.attributes)
>>>>>>
>>>>>>                 def isSpnego = 
>>>>>> authentication.attributes['credentialType']
>>>>>>                 def cc = 
>>>>>> authentication.principal.attributes['costCenter']
>>>>>>
>>>>>>                 if (isSpnego.contains('SpnegoCredential')) {
>>>>>>                         logger.info("Spnego active, bypassing MFA 
>>>>>> [{}]", isSpnego)
>>>>>>                         return null
>>>>>>                 } else {
>>>>>>                         cc.each {
>>>>>>                                 if (it.matches('23K65.+')) {
>>>>>>                                         logger.info("CostCenter TIHA 
>>>>>> [{}]", cc)
>>>>>>                                         logger.info("Activating MFA 
>>>>>> for this authentication session")
>>>>>>                                         return "mfa-duo"
>>>>>>                                 } else {
>>>>>>                                         logger.info("CostCenter 
>>>>>> something else [{}]", cc)
>>>>>>                                         return null
>>>>>>                                 }
>>>>>>                         }
>>>>>>                 }
>>>>>>         }
>>>>>> }
>>>>>>
>>>>>> Good ideas, suggestions, general advice and pointers to best 
>>>>>> practices are more than welcome.
>>>>>> Thank you in advance.
>>>>>> BR,
>>>>>> Otto Myyrä
>>>>>>
>>>>>>

-- 
- Website: https://apereo.github.io/cas
- List Guidelines: https://goo.gl/1VRrw7
- Contributions: https://goo.gl/mh7qDG
--- 
You received this message because you are subscribed to the Google Groups "CAS 
Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/a/apereo.org/d/msgid/cas-user/0f07df90-22ef-4d2f-9f26-882b52e4d962n%40apereo.org.

Reply via email to