Add second MFA provider CAS 6.5

Skip to first unread message

Timothy Hansen

Jul 13, 2022, 12:49:25 PMJul 13
to CAS Community
We recently upgraded our CAS instance to 6.5 as well as began enforcing MFA for all our staff and faculty.  Overall things have been going well but we've had a few people ask about alternative MFA options.  As of right now we use mfa-gauth.

My goal would be to make it so that users could enroll into mfa in and "and/or" kind of scenario.  They could activate mfa-gauth or mfa-u2f depending on their preference.  Or they decide to enroll in both they would then be prompted with a selection page at login to choose the mfa method they plan to use for that given session.  Either way Staff and Faculty will be required to enroll in at least one.

For context on the current setup.  Right now we use mfa-gauth which is triggered with the use of the "cas.authn.mfa.groovy-script.location" setting.  Our groovy script connects to a back end redis database and attempts to find the user in the database.  If the user has mfatype: mfa-gauth set as a key/value in the database then mfa is triggered for that user.  For Faculty and Staff a cronjob runs to add users to that database from a group in AD which enforces mfa for those groups.  For students we have a custom opt-in page where they can just click an "activate" button and they are then added to the database.

In my dev environment I've got u2f dependencies and settings added and successfully tested the u2f method by manually updating my record in the corresponding dev redis db from mfatype: mfa-gauth to mfatype: mfa-u2f.  So at this point I've determined that I can do either or but now I'm stuck on how to go about supporting the ability to enroll in both...

I enabled the "cas.authn.mfa.core.provider-selection-enabled=true" option in my dev environment and so far the only way I've been able to trigger the selection page is by commenting out my groovy script setting and adding this instead ",mfa-u2f" so I at least know I can test the selection page now but that setting isn't going to work for production as it would force everyone into mfa and would prompt everyone with a selection page even if they were enrolled in only one option.  To try and simplify things a bit I took redis out of the equation and tried to just hard code a return value in the script so that it would just always trigger.  I can return a single provider no issue but trying to add a list of providers in the return just causes the script to be ignored and mfa is never prompted.

Hopefully someone can give me some guidance here.  


Jul 15, 2022, 1:11:10 AMJul 15
to CAS Community,
This was also fixed recently but not released in 6.5.x build, the fix is in earliest 6.6.0-RC4 from what I can tell,

Timothy Hansen

Aug 3, 2022, 10:30:05 PMAug 3
to CAS Community, John, Timothy Hansen
Thanks pointing out the fix.  I setup the 6.6 prerelease in a dev environment and was able to adjust our groovy script to get the functionality we wanted.  Will hopefully be implementing this sometime after 6.6 is out of prerelease.

In case it helps anyone:

import java.util.*
import redis.clients.jedis.Jedis
import redis.clients.jedis.JedisPool
import redis.clients.jedis.JedisPoolConfig
import org.apereo.cas.authentication.*
import org.apereo.cas.authentication.mfa.*

def String run(final Object... args) {
    def authentication = args[2]
    try (JedisPool rpool = new JedisPool(new JedisPoolConfig(), "<redis hostname>");) {
        Jedis rdb = rpool.getResource()
        String mfatype = rdb.hget(,"mfatype");
        if(mfatype == null) {
            return null
        if(mfatype.equalsIgnoreCase("mfa-gauth")) {
            return "mfa-gauth"
        if(mfatype.equalsIgnoreCase("mfa-u2f")) {
            return "mfa-u2f"
        if(mfatype.equalsIgnoreCase("all")) {
            return ChainingMultifactorAuthenticationProvider.DEFAULT_IDENTIFIER

Reply all
Reply to author
0 new messages