apereo/cas · error · MultifactorAuthenticationProviderAbsentException
Not all requested multifactor providers could be found…
Error message
Not all requested multifactor providers could be found. Requested providers are [%s] and resolved providers are [%s]
What it means
GlobalMultifactorAuthenticationTrigger.isActivated found that the globally configured MFA provider ids (cas.authn.mfa.global-provider-id) could not all be resolved against the registered MultifactorAuthenticationProvider selection. handleAbsentMultifactorProvider logs a warning and throws MultifactorAuthenticationProviderAbsentException, failing the flow because a mandated provider is missing.
Solutions
- Correct the provider ids in cas.authn.mfa.global-provider-id to match registered provider beans (e.g., mfa-simple, mfa-duo)
- Add the missing MFA provider module/dependency and enable its feature so the provider registers
- Log available provider ids (the warning shows resolved providers) and align config with that list
Example fix
// before cas.authn.mfa.global-provider-id=mfa-gauth,mfa-duoo // after cas.authn.mfa.global-provider-id=mfa-gauth,mfa-duo
Defensive patterns
Strategy: try-catch
Validate before calling
var resolved = providerSelector.getAvailableProviders(); var missing = globalIds.stream().filter(id -> resolved.stream().noneMatch(p -> p.getId().equals(id))).toList(); if (!missing.isEmpty()) { /* fix config before login */ } Try / catch
try { mfaTrigger.isActivated(...); } catch (MultifactorAuthenticationProviderAbsentException e) { log.error("configured MFA provider missing: {}", e.getMessage()); } Prevention
- Cross-check global-provider-id values against resolved provider list at startup
- Add MFA provider modules to the overlay explicitly
- Re-verify provider ids after CAS upgrades
When it happens
Trigger: cas.authn.mfa.global-provider-id lists provider ids (comma-separated) and at least one has no matching registered MultifactorAuthenticationProvider when isActivated runs.
Common situations: Typo in global-provider-id; MFA provider module not added to the overlay so its provider bean never registers; provider id changed after a CAS upgrade; provider conditionally disabled by feature toggle.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- State [ : : ] does not have a matching transition for
- Not all requested multifactor providers could be found…
- Unable to extract credentials for multifactor authentication
- List of candidate multifactor authentication providers is…
- Invalid response format received from Duo
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/2b353512002efc16.
Report an issue: GitHub.
Appendix: source
Thrown at core/cas-server-core-authentication-mfa-api/src/main/java/org/apereo/cas/authentication/mfa/trigger/GlobalMultifactorAuthenticationTrigger.java:119
})
.filter(providers -> !providers.isEmpty())
.orElseGet(() -> {
val globalProviderId = casProperties.getAuthn().getMfa().getTriggers().getGlobal().getGlobalProviderId();
return StringUtils.commaDelimitedListToSet(globalProviderId);
});
}
protected void handleAbsentMultifactorProvider(final Set<String> globalProviderIds,
final List<MultifactorAuthenticationProvider> resolvedProviders) {
val providerIds = resolvedProviders
.stream()
.map(MultifactorAuthenticationProvider::getId)
.collect(Collectors.joining(","));
val message = String.format("Not all requested multifactor providers could be found. "
+ "Requested providers are [%s] and resolved providers are [%s]", globalProviderIds, providerIds);
LOGGER.warn(message, globalProviderIds);
throw new MultifactorAuthenticationProviderAbsentException(message);
}
protected Optional<MultifactorAuthenticationProvider> resolveSingleMultifactorProvider(
final MultifactorAuthenticationProvider resolvedProvider) {
LOGGER.debug("Resolved single multifactor provider [{}]", resolvedProvider);
return Optional.of(resolvedProvider);
}
protected Optional<MultifactorAuthenticationProvider> resolveMultifactorProvider(
final Authentication authentication,
final RegisteredService registeredService,
final List<MultifactorAuthenticationProvider> resolvedProviders) throws Throwable {
val principal = authentication.getPrincipal();
val provider = multifactorAuthenticationProviderSelector.resolve(resolvedProviders, registeredService, principal);
LOGGER.debug("Selected multifactor authentication provider for this transaction is [{}]", provider);
return Optional.ofNullable(provider);
}
}
View on GitHub (pinned to e7288fc434)