Start by stating current deployment uses 6.6.6 with DBMS authentication, not LDAP.
Deployment uses the groovy approach for triggering simple MFA.
Based
on much testing and researching of this archive determined that if
simple MFA is activated through groovy script that CAS will bypass
surrogate selection. From researching this archive others have run into
the same limitation (at least for 6.6.6 and earlier, not sure about
later versions).
For surrogate logging in using the +username / pass approach and then selecting surrogate from drop down.
Surrogate
process functions correctly, but only if MFA not selected by the groovy
script. This is true even if MFA not required in that exact login
instance, having been satisfied by recent/previous login/MFA. For
example, groovy script determines that MFA is required for +username...
system examines recent MFA cache... regardless if MFA required/not
required at this moment.... surrogate process bypassed and
authenticated/released parameters are for original +username.
Current
deployment's security requirements restrict surrogate to internal use
only, while only requiring MFA externally so at this time not an issue
as both MFA and surrogate are working within their separate
external/internal scopes. Future requirements may likely require MFA
internally as well, which with current deployment would conflict with
internal scope surrogate process.
Looking at attached
groovy scripts from other posts it appears they are potentially using
other MFA ("mfa-gauth", "mfa-webauthn"). Perhaps issue with our
deployment is a default web flow issue specific to simple MFA.
Simple
MFA currently works in all instances, but does not flow to
surrogate. If groovy script below returns null for MFA then flow to
surrogate selection works as intended.
import java.util.*
class SampleGroovyProviderSelection {
def String run(final Object... args) {
def service = args[0]
def authentication = args[2]
def request = args[3]
def logger = args[4]
def mfa = null
def email = authentication.principal.attributes['email']
def phone = authentication.principal.attributes['phone']
def mfaMode = authentication.principal.attributes['mfa_mode']
logger.info('Groovy script for mfa')
logger.info(mfaMode)
logger.info(email)
logger.info(phone)
/*
If user lacks both email and phone then bypass MFA
If plan is to prevent the user from authenticating if
they cannot use MFA, that should be handled further upstream
through the DBMS view. It can simply prevent them from
ever authenticating (if that is the desired outcome), in
which case they will never even get to this point
*/
if (mfaMode && (email || phone)) {
if (mfaMode.contains("Y")) {
mfa = ["mfa-simple"]
}
}
return mfa
}
}