CAS 5.3.5 - Delegated Authentication + U2F MFA Credential Issue

55 views
Skip to first unread message

Daniel Ramos

unread,
Oct 26, 2018, 9:04:39 PM10/26/18
to CAS Developer
Whoops, sorry if you all received this more than once. I accidentally submitted this to the old dev mailing list.


I'm trying to setup a new CAS server that delegates authentication but also uses U2F multifactor authentication.

Delegated authentication works fine, but when I try to enable U2F MFA I'm getting errors:
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring4.processor.SpringInputGeneralFieldTagProcessor' (template: "casU2fLoginView" - line 53, col 78)
    at org
.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:117) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
{...}
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'token' cannot be found on object of type 'org.apereo.cas.authentication.principal.ClientCredential' - maybe not public or not valid?

Seems to me instead of a `U2FTokenCredential` being set as the "credential" variable for the template, the Delegated Authentication related `ClientCredential` is being used.

I was able to get it to work by modifying U2FAccountCheckRegistrationAction to include:
WebUtils.putCredential(requestContext,new U2FTokenCredential());

I would *love* to submit a pull request to fix this but I know this isn't the correct fix. I'm not even sure if this issue is specific to U2F or all MFA after a delegated authentication.
Can anyone offer suggestions on where I should look at to fix this correctly? Unfortunately I'm still new to the CAS codebase.

Thank you all.

     - Danny

Brent Smith

unread,
Jul 11, 2019, 11:15:14 AM7/11/19
to CAS Developer
I'm getting this same error when using mfa-simple and mfa-gauth, so it seems like it's related to multiple MFA implementations after delegated auth.  Did you ever find a fix for it?

-Brent

Steve Hillman

unread,
Jul 11, 2019, 1:15:29 PM7/11/19
to Brent Smith, CAS Developer
There’s a bug in the Surrogate Authentication code. Basically when someone authenticates using Delegate Auth, the Surrogate Authentication class overwrites all Credential objects in the Spring Webflow context, rather than just the UsernamePassword Credential. This wipes out the TOTP token credential, giving rise to this error. I’ve fixed it in our local overlay, but I thought it only affected OTP/GAuth authentication. I guess it affects others. Let me see if I can extract a patch

I wanted to submit the patch to the main project, but the code submission guidelines say that patches must be submitted against the master branch (which is 6.x) and back ported to 5.x. We don’t have a working 6.x deploy going anywhere yet, so I’m unable to test patches against the 6.x code base. And many of the 6.x changes are around MFA

--
You received this message because you are subscribed to the Google Groups "CAS Developer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cas-dev+u...@apereo.org.
To view this discussion on the web visit https://groups.google.com/a/apereo.org/d/msgid/cas-dev/df12eaf0-5984-43e6-9ddc-d1367e4b2ef9%40apereo.org.

Steve Hillman 
IT Architect | IT Services
SH1032 | Simon Fraser University 
8888 University Dr., Burnaby, B.C. V5A 1S6
T: 778.782.3960 | M: 604.306.3366www.sfu.ca/itservices
Twitter: @sfu_it

Steve Hillman

unread,
Jul 11, 2019, 4:44:55 PM7/11/19
to Brent Smith, CAS Developer
Two files need to be patched. Here’s the patches against v5.3.7 of the CAS source vs versions we copied into our overlay:

*** ../cas-server/support/cas-server-support-surrogate-webflow/src/main/java/org/apereo/cas/web/flow/action/SurrogateInitialAuthenticationAction.java 2019-01-21 18:02:29.000000000 -0800
--- src/main/java/org/apereo/cas/web/flow/action/SurrogateInitialAuthenticationAction.java 2019-04-11 21:14:39.000000000 -0700
***************
*** 70,75 ****
          }
          WebUtils.putRequestSurrogateAuthentication(context, Boolean.FALSE);
          LOGGER.debug("Converted credential to surrogate for username [{}] and assigned it to webflow", realUsername);
!         WebUtils.putCredential(context, sc);
      }
  }
--- 70,77 ----
          }
          WebUtils.putRequestSurrogateAuthentication(context, Boolean.FALSE);
          LOGGER.debug("Converted credential to surrogate for username [{}] and assigned it to webflow", realUsername);
!         // SFU Addition : change to call new replaceCredential method, which will only replace the Username credential
!         // with the Surrogate credential in scopes where the Username credential previously existed
!         WebUtils.replaceCredential(context, sc, UsernamePasswordCredential.class);
      }
  }
-------------------

*** ../cas-server/core/cas-server-core-web-api/src/main/java/org/apereo/cas/web/support/WebUtils.java 2019-01-21 18:36:37.000000000 -0800
--- src/main/java/org/apereo/cas/web/support/WebUtils.java 2019-04-11 21:14:39.000000000 -0700
***************
*** 398,403 ****
--- 398,431 ----
          }
      }
  
+     // SFU Addition
+     /**
+      * Replaces credential in the context
+      * Only instances of credential in the context that are of type clazz will be replaced
+      * @param context the content
+      * @param c       the credential
+      * @param clazz   Class type to replace
+      */
+     public static void replaceCredential(final RequestContext context, final Credential c, @NonNull final Class clazz) {
+         if (c == null) {
+             // We don't remove - only replace
+             return;
+         }
+         final Credential cFromRequest = (Credential) context.getRequestScope().get(PARAMETER_CREDENTIAL, clazz);
+         final Credential cFromFlow = (Credential) context.getFlowScope().get(PARAMETER_CREDENTIAL, clazz);
+         final Credential cFromConversation = (Credential) context.getConversationScope().get(PARAMETER_CREDENTIAL, clazz);
+         if (cFromRequest != null) {
+             context.getRequestScope().put(PARAMETER_CREDENTIAL, c);
+         }
+         if (cFromFlow != null) {
+             context.getFlowScope().put(PARAMETER_CREDENTIAL, c);
+         }
+         if (cFromConversation != null) {
+             context.getConversationScope().put(PARAMETER_CREDENTIAL, c);
+         }
+     }
+     //
  
      /**
       * Is authenticating at a public workstation?




Reply all
Reply to author
Forward
0 new messages