apereo/cas · critical · AuthenticationException

No authentication handlers could be resolved to support the…

Error message

No authentication handlers could be resolved to support the authentication transaction

What it means

DefaultAuthenticationEventExecutionPlan.resolveAuthenticationHandlers throws AuthenticationException when, after filtering by credential support (and MFA handling), the resolved handler set is empty — no registered handler can support any credential in the transaction, so authentication cannot proceed.

Solutions

  1. Register/enable at least one authentication handler supporting the submitted credential type (LDAP, JDBC, accept-users, etc.)
  2. Verify handler module dependencies are present and features enabled so beans get created
  3. Check multifactor/authentication policy configuration that may be filtering handlers out by name
  4. Inspect resolved handler logs ('Resolved and finalized authentication handlers') to see what was eligible

Example fix

// before
cas.authn.ldap[0].search-filter=(uid={user})  # but LDAP handler feature disabled -> zero handlers
// after
# add the LDAP authentication module / enable the feature so the handler bean is registered
cas.authn.ldap[0].ldap-url=ldaps://ldap.example.org
Defensive patterns

Strategy: try-catch

Validate before calling

// before authenticating, confirm handlers exist for the credential
boolean supported = executionPlan.resolveAuthenticationHandlers(transaction).stream()
    .anyMatch(h -> h.supports(transaction.getCredentials().iterator().next()));

Try / catch

try {
    Authentication auth = authenticationManager.authenticate(transaction);
} catch (AuthenticationException e) {
    if (e.getMessage().contains("No authentication handlers could be resolved")) {
        LOGGER.error("Enable at least one authn handler supporting credential type [{}]",
            transaction.getCredentials().iterator().next().getClass().getSimpleName());
    }
}

Prevention

When it happens

Trigger: authenticate() is invoked with credentials for which no handler is registered or eligible: all candidate handlers disabled/removed by MFA resolution, handler names not matching credential handlers, or handlers not registered in the plan at all.

Common situations: CAS deployed with no enabled authentication sources (e.g. accept-users and all LDAP/JDBC handlers disabled); misconfigured multifactor policy filtering out all handlers; handler bean missing because its module is not on the classpath.

Understand the failure class

Related errors


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

Appendix: source

Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/DefaultAuthenticationEventExecutionPlan.java:199

        if (resolvedHandlers.isEmpty()) {
            LOGGER.debug("Authentication handler resolvers produced no candidate authentication handler. Using the default handler resolver instead...");
            if (defaultAuthenticationHandlerResolver.supports(handlers, transaction)) {
                resolvedHandlers.addAll(defaultAuthenticationHandlerResolver.resolve(handlers, transaction));
            }
        }

        val byCredential = new ByCredentialSourceAuthenticationHandlerResolver();
        if (byCredential.supports(resolvedHandlers, transaction)) {
            val credentialHandlers = byCredential.resolve(resolvedHandlers, transaction);
            if (!credentialHandlers.isEmpty()) {
                LOGGER.debug("Authentication handlers resolved by credential source are [{}]", credentialHandlers);
                resolvedHandlers.removeIf(handler -> !(handler instanceof MultifactorAuthenticationHandler)
                    && credentialHandlers.stream().noneMatch(credHandler -> Strings.CI.equals(credHandler.getName(), handler.getName())));
            }
        }

        if (resolvedHandlers.isEmpty()) {
            throw new AuthenticationException("No authentication handlers could be resolved to support the authentication transaction");
        }
        LOGGER.debug("Resolved and finalized authentication handlers to carry out this authentication transaction are [{}]", handlerResolvers);
        return resolvedHandlers;
    }

    @Override
    public Set<AuthenticationHandler> resolveAuthenticationHandlers() {
        val clientInfo = ClientInfoHolder.getClientInfo();
        val handlers = authenticationHandlerPrincipalResolverMap
            .keySet()
            .stream()
            .filter(BeanSupplier::isNotProxy)
            .filter(handler -> {
                if (clientInfo != null && StringUtils.isNotBlank(clientInfo.getTenant())) {
                    val tenantDefinition = tenantExtractor.getTenantsManager().findTenant(clientInfo.getTenant()).orElseThrow();
                    val authenticationHandlers = tenantDefinition.getAuthenticationPolicy() != null
                        ? tenantDefinition.getAuthenticationPolicy().getAuthenticationHandlers()
                        : List.of();

View on GitHub (pinned to e7288fc434)