Yan, The doExecute method gets the RequestContext https://docs.spring.io/spring-webflow/docs/current/api/org/springframework/webflow/execution/RequestContext.html, which has a number of maps. At least one of them should have an object(s) that represents the successful login (hopefully it will be mutable). You could then redirect to the login page (the initial URL will also be in one of the maps).
Ray P.S. Note: if you are logging the contents of the request context maps, some of them will have the user's credentials P.P.S here is a method to format the flow (AbstractCasWebflowConfigurer has a getLoginFlow method): /** * Formats a spring webflow flow to help determine how to modify a flow. * Adds new lines and indents to make it easier to read. * @param input flow.toString() * @return nicely formatted flow */ public String formatFlow(final String input) { //LOGGER.debug("input: ." + input + "."); // used to add an extra indent for an object's field members java.util.Stack<java.util.AbstractMap.SimpleEntry> stack = new java.util.Stack<>(); int currPosition = 0; String indent = ""; String indentor = "\t"; String newLine = "\n"; // object identifier java.util.regex.Pattern objPattern = Pattern.compile("^(\\w+@\\w+)\\b.*"); String in = input.trim(); StringBuilder out = new StringBuilder(); while (in.length() > currPosition) { java.util.regex.Matcher m = objPattern.matcher(in.substring(currPosition)); String firstTwo = ""; // capture first two characters to match against ']' or '],' if (1 < in.length() - currPosition) { firstTwo = in.substring(currPosition, currPosition + 2); } else { // at end of input firstTwo = in.substring(currPosition, currPosition + 1); } if (in.startsWith("[", currPosition)) { out.append(indent).append(in.charAt(currPosition)).append(newLine); indent += indentor; currPosition++; if (!stack.empty()) { java.util.AbstractMap.SimpleEntry<String, Integer> se = stack.pop(); se.setValue(se.getValue() + 1); stack.push(se); } } else if (firstTwo.startsWith("]")) { if (!stack.empty()) { java.util.AbstractMap.SimpleEntry<String, Integer> se = stack.pop(); if (1 > se.getValue()) { // outdent after printing member variables indent = indent.replaceFirst(indentor, ""); if (!stack.empty()) { // this ] closes from outer object java.util.AbstractMap.SimpleEntry<String, Integer> seOuter = stack.pop(); seOuter.setValue(seOuter.getValue() - 1); stack.push(seOuter); } } else { se.setValue(se.getValue() - 1); stack.push(se); } } indent = indent.replaceFirst(indentor, ""); out.append(indent).append("]"); if ("],".equals(firstTwo)) { out.append(","); currPosition++; } out.append(newLine); currPosition++; } else if (m.matches()) { String obj = m.group(1); out.append(indent).append(obj).append(newLine); indent = indent + indentor; // prepare for members stack.push(new java.util.AbstractMap.SimpleEntry<String, Integer>(obj, 0)); currPosition += obj.length(); } else { int nextOpenBracket = in.indexOf("[", currPosition); int nextCloseBracket = in.indexOf("]", currPosition); int nextComma = in.indexOf(",", currPosition); int nextMark = 0; boolean increaseIndent = false; // if [ or , not found, push beyond last position which would be ] if (0 > nextOpenBracket) { nextOpenBracket = in.length(); } if (0 > nextComma) { nextComma = in.length(); } // add 1 when [ and , since they should remain on same line and ] should be on next line if (nextCloseBracket > nextOpenBracket) { if (nextOpenBracket > nextComma) { nextMark = nextComma + 1; } else { nextMark = nextOpenBracket + 1; // bypass empty and null if ((in.substring(nextMark).startsWith("[empty]]")) || (in.substring(nextMark).startsWith("null]"))) { if (in.substring(nextMark).startsWith("[empty]],")) { nextMark += 9; } else if (in.substring(nextMark).startsWith("[empty]]")) { nextMark += 8; } else if (in.substring(nextMark).startsWith("null],")) { nextMark += 6; } else if (in.substring(nextMark).startsWith("null]")) { nextMark += 5; } } else { // indent members increaseIndent = true; if (!stack.empty()) { java.util.AbstractMap.SimpleEntry<String, Integer> se = stack.pop(); se.setValue(se.getValue() + 1); stack.push(se); } } } } else if (nextCloseBracket > nextComma) { nextMark = nextComma + 1; } else { nextMark = nextCloseBracket; } String s = in.substring(currPosition, nextMark).trim(); if (0 < s.length()) { out.append(indent).append(s).append(newLine); currPosition = nextMark; } if (increaseIndent) { // for next line indent = indent + indentor; } } } String formatted = out.toString().trim(); //LOGGER.debug("formatted: ." + formatted + "."); return formatted; } On Wed, 2024-02-21 at 13:04 -0800, Yan Zhou wrote: Notice: This message was sent from outside the University of Victoria email system. Please be cautious with links and sensitive information. Hi, CAS 6.6.x with MFA. After I correctly enter user credentials, I will be asked for a code, if that fails, CAS shows casMfaDeniedView. The following CAS code (if user enters incorrect code) simply takes user back to MFA login page, so that user can retry. I would not want users to have unlimited retry, so I want to extend the flow, adding a button that takes user back to login page, clearing credentials already established during the initial login flow. But, MFA flow and Login flow are two different flows, i have trouble to implement this correctly. How do you do this? Thanks, Yan val realSubmitState = createActionState(flow, CasWebflowConstants.STATE_ID_REAL_SUBMIT, createEvaluateAction(CasWebflowConstants.ACTION_ID_OTP_AUTHENTICATION_ACTION)); createTransitionForState(realSubmitState, CasWebflowConstants.TRANSITION_ID_SUCCESS, CasWebflowConstants.STATE_ID_SUCCESS); createTransitionForState(realSubmitState, CasWebflowConstants.TRANSITION_ID_ERROR, CasWebflowConstants.STATE_ID_VIEW_LOGIN_FORM); -- - 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/674db08904ecc0bbe19b9ccd4d0ebc65a045bf4c.camel%40uvic.ca.