apereo/cas · error · AuthenticationException
No multifactor authentication providers are available in…
Error message
No multifactor authentication providers are available in the application context. Authentication is blocked
What it means
MultifactorAuthenticationContingencyPlan.executeInternal() determines which MFA provider should handle a risky authentication. When no explicit provider is configured, it queries the context for available MFA providers; if the provider map is empty it logs this warning and throws AuthenticationException wrapping RiskyAuthenticationException, blocking the authentication outright. Risky logins cannot be remediated because no provider exists to step them up.
Solutions
- Add and configure at least one MFA provider (e.g. cas-server-support-otp-mfa or mfa-totp) and enable it via cas.authn.mfa.<provider>.* properties.
- Set cas.authn.adaptive.risk.response.mfa-provider to the id of an available provider so the plan does not depend on discovery.
- Confirm the MFA module's auto-configuration is active and its provider bean appears in the context (check ConditionalOnFeatureEnable).
- If MFA is not intended, adjust the risk response mode (e.g. block/audit) instead of relying on an MFA provider that does not exist.
Example fix
// before: risk response expects MFA but no provider configured // (no cas.authn.mfa.* properties, no MFA module) // after: configure a provider and point the risk response at it cas.authn.mfa.totp.enabled=true cas.authn.adaptive.risk.response.mfa-provider=mfa-totp
Defensive patterns
Strategy: validation
Validate before calling
val providers = MultifactorAuthenticationUtils
.getAvailableMultifactorAuthenticationProviders(applicationContext);
if (casProperties.getAuthn().getAdaptive().getRisk().isEnabled()
&& providers.isEmpty()) {
throw new IllegalStateException("Risk-based auth requires at least one MFA provider");
} Try / catch
try {
contingencyPlan.handle(riskyAuthEvent, authentication, service, request);
} catch (AuthenticationException e) {
if (e.hasExceptionOfType(RiskyAuthenticationException.class)) {
// degrade to block/deny flow or alert operator
return blockedResponse(authentication);
}
throw e;
} Prevention
- Enable an MFA module whenever adaptive risk response mode requires MFA.
- Set cas.authn.adaptive.risk.response.mfa-provider explicitly at deploy time.
- Assert provider availability in a startup health check.
- Keep risk-response mode and available MFA modules in the same deployment checklist.
When it happens
Trigger: A risky authentication is detected (cas.authn.adaptive.risk response triggered), cas.authn.adaptive.risk.response.mfaProvider is blank, and MultifactorAuthenticationUtils.getAvailableMultifactorAuthenticationProviders(applicationContext) returns an empty map — no MFA module (mfa-duo, mfa-totp, mfa-webauthn, etc.) is configured/enabled.
Common situations: Adaptive risk enabled in an overlay that has no MFA support module at all; MFA module present but its auto-configuration disabled or its provider bean conditionally skipped; typo'd/unsupported provider id in cas.authn.mfo.* leaving no provider registered.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No multifactor authentication providers are specified to…
- No risk calculators are available to evaluate…
- State [ : : ] does not have a matching transition for
- Not all requested multifactor providers could be found…
- Unable to extract credentials for multifactor authentication
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/5ca0f18d758de0d5.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/plans/MultifactorAuthenticationContingencyPlan.java:44
@Slf4j
public class MultifactorAuthenticationContingencyPlan extends BaseAuthenticationRiskContingencyPlan {
public MultifactorAuthenticationContingencyPlan(final CasConfigurationProperties casProperties,
final ApplicationContext applicationContext) {
super(casProperties, applicationContext);
}
@Override
protected AuthenticationRiskContingencyResponse executeInternal(final Authentication authentication,
final RegisteredService service,
final AuthenticationRiskScore score,
final HttpServletRequest request) {
var id = casProperties.getAuthn().getAdaptive().getRisk().getResponse().getMfaProvider();
if (StringUtils.isBlank(id)) {
LOGGER.debug("No explicit multifactor authentication provider is defined to handle risk-based authentication.");
val providerMap = MultifactorAuthenticationUtils.getAvailableMultifactorAuthenticationProviders(this.applicationContext);
if (providerMap.isEmpty()) {
LOGGER.warn("No multifactor authentication providers are available in the application context. Authentication is blocked");
throw new AuthenticationException(new RiskyAuthenticationException());
}
if (providerMap.size() == 1) {
id = providerMap.values().iterator().next().getId();
} else {
LOGGER.warn("No multifactor authentication providers are specified to handle risk-based authentication");
throw new AuthenticationException(new MultifactorAuthenticationProviderAbsentException());
}
}
LOGGER.debug("Attempting to handle risk-based authentication via multifactor authentication provider [{}]", id);
val attributeName = casProperties.getAuthn().getAdaptive().getRisk().getResponse().getRiskyAuthenticationAttribute();
val newAuthn = DefaultAuthenticationBuilder.newInstance(authentication)
.addAttribute(attributeName, Boolean.TRUE)
.build();
LOGGER.debug("Updated authentication to remember risk-based authentication via [{}]", attributeName);
authentication.updateAttributes(newAuthn);View on GitHub (pinned to e7288fc434)