Maybe Misagh could put in his thoughts on this, but I would argue the opposite is more true in fact, having custom java code and having to register, etc.. rely's on way MORE base code in cas then the groovy methods. If you take a look at the way groovy scripts are written in cas it is mainly a simple execute groovy method passing the parameters and just reading the results. That code itself doesn't change much, we had thousands of lines of custom java code before the 6.x days, for all kinds of things. Now we maintain 2 individual java class files and working to get those changes pushed into cas, just need to write the test cases and scenarios.
One of the benefits to using groovy is the no compile time, they don't need to be compiled with your overlay! most if not all groovy scripts are reloaded on demand, when changed and take affect immediately with no restarts which makes a huge difference. Not sure why the other posters simple-mfa wouldnt work but works no problem for us, it could be the trigger type being used, there is the cas.authn.mfa.core.provider-selector-groovy-script and what we use, cas.authn.mfa.groovy-script and we have some vendors/external services that use database auth and mfa is fine, we also use surrogate and in our groovy we have parts written to either bypass/force for surrogate situations. We have been using CAS since the 3.x days and when groovy webflow came along, it was a blessing!! It is soooo much easier to maintain then custom java code. See the attached, this is one of about 4 different flow modifiers, using the "properties" in a service definition, we utilize this flow to inject custom post fields for services that require a POST response instead of REDIRECT. I think, in my opinion, groovy is way more sustainable to maintain then the other. Thanks, John On Tuesday, July 25, 2023 at 7:18:07 AM UTC-5 spfma...@e.mail.fr wrote: > Hi, > Thanks for your reply. > From what I have read in the recommendations in the docs, scripting is ok > but coding is better and more sustainable (build time vs run time I guess). > So I am trying to understand how to implement something like what is > described here : > https://apereo.github.io/cas/6.6.x/mfa/Configuring-Multifactor-Authentication-Triggers-Custom.html > But so far I don't even know where to put the code, how to even have a > single debug log line. > Thanks for this example (I think I saw it a couple of monthes ago),if will > follow this way if it's the right one too. > But I can't forget I have to replicate an old "login-webflow.xml", which > seems to be done programmatically only in current version. > Regards > > > Le 21-Jul-2023 20:00:53 +0200, rb...@uvic.ca a écrit: > > This may provide some direction > https://fawnoos.com/2018/11/22/cas5-groovy-mfa/ > There may be other posts on this site that can help. > > Ray > > On Fri, 2023-07-21 at 08:49 +0200, spfma.tech via CAS Community wrote: > > Notice: This message was sent from outside the University of Victoria > email system. Please be cautious with links and sensitive information. > > Hi, > I would like to implement some conditional MFA scenarios (using a > different provider depending on the network is the first one), but reading > https://apereo.github.io/cas/6.6.x/mfa/Configuring-Multifactor-Authentication-Triggers-Custom.html > > does not provide a lot of help. > Is there some code snippet available somewhere I could use as an example ? > Regards > > ------------------------------ > FreeMail powered by mail.fr > > > > > > > > ------------------------------ > FreeMail powered by mail.fr -- - Website: https://apereo.github.io/cas - Gitter Chatroom: https://gitter.im/apereo/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 cas-user+unsubscr...@apereo.org. To view this discussion on the web visit https://groups.google.com/a/apereo.org/d/msgid/cas-user/fd892674-8cea-4f49-a814-568482278b47n%40apereo.org.
if (webflow.containsFlowState(loginFlow, CasWebflowConstants.STATE_ID_GENERATE_SERVICE_TICKET)) { logger.debug("Webflow: Found state that modifys the generateServiceTicketAction"); def state = webflow.getState(loginFlow, CasWebflowConstants.STATE_ID_GENERATE_SERVICE_TICKET, ActionState.class) logger.debug("Webflow: State id is {}", state.id); state.getExitActionList().add({ requestContext -> def flowScope = requestContext.flowScope def httpRequest = WebUtils.getHttpServletRequestFromExternalWebflowContext(requestContext); def requestScope = requestContext.getRequestScope(); def authentication = WebUtils.getAuthentication(requestContext) as Authentication; def principal = authentication.getPrincipal() as Principal; def service = WebUtils.getRegisteredService(requestContext); def serviceClass = service.class.getSimpleName().toLowerCase(); if (serviceClass == "casregisteredservice") { def serviceProperties = service.properties; def serviceType = (StringUtils.isNotBlank(service.getResponseType())) ? service.getResponseType().toLowerCase() : "redirect"; def serviceTicket = WebUtils.getServiceTicketFromRequestScope(requestContext); def servicePolicy = service.getAttributeReleasePolicy(); def addCreds = servicePolicy.isAuthorizedToReleaseCredentialPassword(); def userAttr = principal.getAttributes(); def userProvider = service.getUsernameAttributeProvider(); def uid = (userProvider.hasProperty("usernameAttribute")) ? userAttr.get(userProvider.usernameAttribute)[0] : principal.id; if (serviceType == "post") { logger.debug("Webflow: Response type POST is marked for inclusion"); logger.debug("Webflow: Checking for custom post fields"); if (serviceProperties.containsKey("postFields")) { if (serviceProperties.postFields.value) { addFields = serviceProperties.postFields.value; logger.debug("Webflow: Custom post fields are defined, adding to scope {}", addFields); addFields.splitEachLine(",") { it.each{ x -> def object = x.split("=") def fieldsObj = [:] fieldsObj.put(object[0], object[1]) logger.debug("Webflow: Adding extra field {} with value {}", object[0], object[1]); requestScope.put("custom_fields", fieldsObj); } } logger.debug("Webflow: Done adding custom post fields"); } } else { logger.debug("Webflow: Custom post fields are not defined so we will not add any"); } logger.debug("Webflow: Checking for custom post url"); if (serviceProperties.containsKey("postUrl")) { if (serviceProperties.postUrl.value) { paramAdd = "?"; post_url = serviceProperties.postUrl.value; if (post_url.contains('?')) { paramAdd = "&"; } requestScope.put("custom_postUrl", post_url + paramAdd + "ticket=" + serviceTicket); logger.debug("Webflow: Custom post url is defined {}", post_url); } } else { logger.debug("Webflow: Custom post url not defined so we will not add one"); } } else { logger.debug("Webflow: Response type {} is excluded", serviceType); } } return null; }) }