{"record":{"id":"5ca0f18d758de0d5","repo":"apereo/cas","slug":"no-multifactor-authentication-providers-are-availa","errorCode":null,"errorMessage":"No multifactor authentication providers are available in the application context. Authentication is blocked","messagePattern":"No multifactor authentication providers are available in the application context\\. Authentication is blocked","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/plans/MultifactorAuthenticationContingencyPlan.java","lineNumber":44,"sourceCode":"@Slf4j\npublic class MultifactorAuthenticationContingencyPlan extends BaseAuthenticationRiskContingencyPlan {\n\n    public MultifactorAuthenticationContingencyPlan(final CasConfigurationProperties casProperties,\n                                                    final ApplicationContext applicationContext) {\n        super(casProperties, applicationContext);\n    }\n\n    @Override\n    protected AuthenticationRiskContingencyResponse executeInternal(final Authentication authentication,\n                                                                    final RegisteredService service,\n                                                                    final AuthenticationRiskScore score,\n                                                                    final HttpServletRequest request) {\n        var id = casProperties.getAuthn().getAdaptive().getRisk().getResponse().getMfaProvider();\n        if (StringUtils.isBlank(id)) {\n            LOGGER.debug(\"No explicit multifactor authentication provider is defined to handle risk-based authentication.\");\n            val providerMap = MultifactorAuthenticationUtils.getAvailableMultifactorAuthenticationProviders(this.applicationContext);\n            if (providerMap.isEmpty()) {\n                LOGGER.warn(\"No multifactor authentication providers are available in the application context. Authentication is blocked\");\n                throw new AuthenticationException(new RiskyAuthenticationException());\n            }\n\n            if (providerMap.size() == 1) {\n                id = providerMap.values().iterator().next().getId();\n            } else {\n                LOGGER.warn(\"No multifactor authentication providers are specified to handle risk-based authentication\");\n                throw new AuthenticationException(new MultifactorAuthenticationProviderAbsentException());\n            }\n        }\n\n        LOGGER.debug(\"Attempting to handle risk-based authentication via multifactor authentication provider [{}]\", id);\n        val attributeName = casProperties.getAuthn().getAdaptive().getRisk().getResponse().getRiskyAuthenticationAttribute();\n        val newAuthn = DefaultAuthenticationBuilder.newInstance(authentication)\n            .addAttribute(attributeName, Boolean.TRUE)\n            .build();\n        LOGGER.debug(\"Updated authentication to remember risk-based authentication via [{}]\", attributeName);\n        authentication.updateAttributes(newAuthn);","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-electrofence/src/main/java/org/apereo/cas/impl/plans/MultifactorAuthenticationContingencyPlan.java#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: risk response expects MFA but no provider configured\n// (no cas.authn.mfa.* properties, no MFA module)\n// after: configure a provider and point the risk response at it\ncas.authn.mfa.totp.enabled=true\ncas.authn.adaptive.risk.response.mfa-provider=mfa-totp","handlingStrategy":"validation","validationCode":"val providers = MultifactorAuthenticationUtils\n    .getAvailableMultifactorAuthenticationProviders(applicationContext);\nif (casProperties.getAuthn().getAdaptive().getRisk().isEnabled()\n    && providers.isEmpty()) {\n    throw new IllegalStateException(\"Risk-based auth requires at least one MFA provider\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    contingencyPlan.handle(riskyAuthEvent, authentication, service, request);\n} catch (AuthenticationException e) {\n    if (e.hasExceptionOfType(RiskyAuthenticationException.class)) {\n        // degrade to block/deny flow or alert operator\n        return blockedResponse(authentication);\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["mfa","risk-authentication","electrofence","authentication-blocked"],"backgroundTag":"missing-dependency","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}