apereo/cas · critical · AuthenticationException

MultifactorAuthenticationProviderAbsentException

Error message

MultifactorAuthenticationProviderAbsentException

What it means

RadiusAccessChallengedMultifactorAuthenticationTrigger.isActivated throws AuthenticationException wrapping MultifactorAuthenticationProviderAbsentException when it needs to resolve the RADIUS MFA provider but the application context has no registered multifactor authentication providers at all. The RADIUS access-challenge flow cannot be activated without an MFA provider.

Solutions

  1. Add the radius-mfa support module (cas-server-support-radius-mfa) to the build so the provider bean is registered
  2. Confirm no MFA feature flags/exclusions are disabling the radius provider (@ConditionalOnFeatureEnabled)
  3. Check startup logs for the MFA provider bean failing to create (missing cas.authn.mfa.radius config)
  4. Verify the application context actually contains a bean implementing MultifactorAuthenticationProvider

Example fix

// before: build.gradle (webapp overlay) missing MFA module
// implementation 'org.apereo.cas:cas-server-support-radius'
// after
implementation 'org.apereo.cas:cas-server-support-radius'
implementation 'org.apereo.cas:cas-server-support-radius-mfa'
Defensive patterns

Strategy: validation

Validate before calling

var providers = MultifactorAuthenticationUtils
    .getAvailableMultifactorAuthenticationProviders(applicationContext);
if (providers.isEmpty()) {
    throw new IllegalStateException("No MFA providers registered; radius-mfa module missing");
}

Type guard

boolean radiusMfaReady(ApplicationContext ctx) {
    return !MultifactorAuthenticationUtils
        .getAvailableMultifactorAuthenticationProviders(ctx)
        .isEmpty();
}

Try / catch

try {
    trigger.isActivated(...);
} catch (AuthenticationException e) {
    // abort challenge flow; radius-mfa provider not present
}

Prevention

When it happens

Trigger: A RADIUS access challenge (State packet) is detected during authentication, the trigger runs, and MultifactorAuthenticationUtils.getAvailableMultifactorAuthenticationProviders(applicationContext) returns an empty map.

Common situations: cas-server-support-radius-mfa module not on the classpath so no provider bean is registered; all MFA providers excluded/disabled by feature flags; the radius MFA provider bean failed to initialize (missing RADIUS server config); running a webapp assembly that omits MFA auto-configuration.

Understand the failure class

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/58ea0b340a71b36c. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-radius/src/main/java/org/apereo/cas/adaptors/radius/web/flow/RadiusAccessChallengedMultifactorAuthenticationTrigger.java:61

    @Override
    public Optional<MultifactorAuthenticationProvider> isActivated(final Authentication authentication,
                                                                   final RegisteredService registeredService,
                                                                   final HttpServletRequest request,
                                                                   final HttpServletResponse response,
                                                                   final Service service) {
        if (authentication == null) {
            LOGGER.debug("No authentication or service is available to determine event for principal");
            return Optional.empty();
        }
        if (!supports(authentication)) {
            LOGGER.trace("Authentication attempt does not qualify for radius multifactor authentication");
            return Optional.empty();
        }
        
        val providerMap = MultifactorAuthenticationUtils.getAvailableMultifactorAuthenticationProviders(this.applicationContext);
        if (providerMap.isEmpty()) {
            LOGGER.error("No multifactor authentication providers are available in the application context");
            throw new AuthenticationException(new MultifactorAuthenticationProviderAbsentException());
        }

        val id = casProperties.getAuthn().getMfa().getRadius().getId();
        LOGGER.debug("Authentication requires multifactor authentication via provider [{}]", id);
        return MultifactorAuthenticationUtils.resolveProvider(providerMap, id);

    }

    private static boolean supports(final Authentication authentication) {
        val principal = authentication.getPrincipal();
        val attributes = principal.getAttributes();
        LOGGER.debug("Evaluating principal attributes [{}] for multifactor authentication", attributes.keySet());
        return attributes.containsKey(Attr_ReplyMessage.NAME) && attributes.containsKey(Attr_State.NAME);
    }
}

View on GitHub (pinned to e7288fc434)