apereo/cas · error · InsufficientAuthenticationException

Unexpected LDAP error

Error message

Unexpected LDAP error

What it means

EndpointLdapAuthenticationProvider.authenticate() wraps any Throwable raised during LDAP authentication into InsufficientAuthenticationException("Unexpected LDAP error", cause) after logging it. It is a catch-all signaling the LDAP operation itself blew up (connection failure, timeout, communication error), as distinct from bad credentials.

Solutions

  1. Read the logged cause (LoggingUtils.error) — it names the real connection/TLS problem
  2. Verify cas.authn.ldap[x].ldap-url, port, and that the server is reachable (ldapsearch/openssl s_client)
  3. Check StartTLS and trust-store settings (validate-on-tls, keystore config)
  4. Review connection pool sizing/timeouts (min/max pool size, block wait time)
  5. Restore directory availability / network path

Example fix

// before
// ldap-url=ldap://directory.example.org:10389
// after (correct host/port + pool tuning)
// ldap-url=ldaps://directory.example.org:636
// connection-strategy=ACTIVE_PASSIVE
// pool.max-size=20
Defensive patterns

Strategy: try-catch

Validate before calling

// connectivity precheck before authenticate
try (Connection c = DefaultConnectionFactory connections.newConnection(props)) {
    c.open(); // throws if host/port/TLS unreachable
}

Try / catch

try {
    provider.authenticate(token);
} catch (InsufficientAuthenticationException e) {
    logger.error("LDAP infrastructure error: {}", e.getCause(), e); // inspect cause for connection/TLS detail
    throw new ServiceUnavailableException("Directory temporarily unavailable");
}

Prevention

When it happens

Trigger: authenticator.authenticate(request) throws — unreachable LDAP host/port, TLS handshake failure, connection-pool timeout, DNS failure, or any runtime exception inside the ldaptive stack.

Common situations: Wrong ldapUrl/port; firewall blocks the connection; certificate not trusted (StartTLS/LDAPS); directory temporarily down; connection pool exhausted under load.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/authorization/EndpointLdapAuthenticationProvider.java:110

                val entry = response.getLdapEntry();
                val attributes = new HashMap<String, List<Object>>();
                entry.getAttributes().forEach(attribute -> attributes.put(attribute.getName(), new ArrayList<>(attribute.getStringValues())));
                val principal = PrincipalFactoryUtils.newPrincipalFactory().createPrincipal(username, attributes);
                val authZGen = buildAuthorizationGenerator();
                val authorities = authZGen.apply(Objects.requireNonNull(principal));

                LOGGER.debug("List of authorities remapped from profile roles are [{}]", authorities);
                if (authorities.stream().anyMatch(authority -> requiredRoles.contains(authority.getAuthority()))) {
                    return generateAuthenticationToken(authentication, authorities);
                }
                LOGGER.warn("User [{}] is not authorized to access the requested resource", username);
            } else {
                LOGGER.warn("LDAP authentication response produced no results for [{}]", username);
            }

        } catch (final Throwable e) {
            LoggingUtils.error(LOGGER, e);
            throw new InsufficientAuthenticationException("Unexpected LDAP error", e);
        }
        throw new BadCredentialsException("Could not authenticate provided credentials");
    }

    @Override
    public boolean supports(final Class<?> aClass) {
        return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
    }

    private Function<Principal, List<SimpleGrantedAuthority>> buildAuthorizationGenerator() {
        val properties = ldapProperties.getLdapAuthz();

        if (isGroupBasedAuthorization()) {
            LOGGER.debug("Handling LDAP authorization based on groups");
            return new LdapUserGroupsToRolesAuthorizationGenerator(
                ldapAuthorizationGeneratorUserSearchOperation(),
                properties.isAllowMultipleResults(),
                properties.getGroupAttribute(),

View on GitHub (pinned to e7288fc434)