apereo/cas · error · AccountNotFoundException

DN resolution failed.

Error message

DN resolution failed. [{}]

What it means

CAS's LDAP authentication handler throws AccountNotFoundException when the LDAP authentication result code is DN_RESOLUTION_FAILURE, meaning the directory could not resolve the supplied username to an entry DN. Unlike a wrong password, this means no matching user entry exists under the configured base DNs/search filters. The message logs the server's diagnostic message for details.

Solutions

  1. Verify the username exists in the directory under the configured baseDn
  2. Review cas.authn.ldap[0].userFilter / searchFilter and test it directly with ldapsearch for the failing user
  3. Correct baseDn so the search scope actually contains user accounts
  4. Check the logged diagnostic message [{}] for the exact filter/DN used
  5. If users legitimately should not authenticate, handle AccountNotFoundException in the caller rather than changing config

Example fix

// before
cas.authn.ldap[0].userFilter=uid={user},ou=people,dc=example,dc=org
// users actually live under a different OU
// after
cas.authn.ldap[0].baseDn=ou=accounts,dc=example,dc=org
cas.authn.ldap[0].userFilter=(uid={user})
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the user exists before authenticating, using the same filter
String filter = "(uid=" + LdapUtils.encodeLdapFilterValue(username) + ")";
boolean exists = !connection.search(baseDn, SearchScope.SUBTREE, filter).getEntries().isEmpty();

Type guard

if (AuthenticationResultCode.DN_RESOLUTION_FAILURE == response.getAuthenticationResultCode()) {
    throw new AccountNotFoundException(username);
}

Try / catch

try {
    return ldapHandler.authenticate(credential);
} catch (AccountNotFoundException e) {
    return AuthenticationResult.UNKNOWN_USER;
} catch (FailedLoginException e) {
    return AuthenticationResult.FAILED;
}

Prevention

When it happens

Trigger: authenticateUsernamePasswordInternal receives a response whose isSuccess() is false and whose getAuthenticationResultCode() equals AuthenticationResultCode.DN_RESOLUTION_FAILURE — i.e. the user search/filter matched no entry, so no DN could be resolved for bind.

Common situations: Typo'd or wrong username; users located outside the configured baseDn; userSearchFilter too restrictive (e.g. extra objectClass conditions the accounts lack); case or attribute mismatch (searching uid vs sAMAccountName); user disabled/removed but credentials cached client-side.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


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

Appendix: source

Thrown at support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/authentication/LdapAuthenticationHandler.java:135

    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential upc,
                                                                                        @Nullable final String originalPassword) throws Throwable {
        val response = getLdapAuthenticationResponse(upc);
        LOGGER.debug("LDAP response: [{}]", response);
        if (!passwordPolicyHandlingStrategy.supports(response)) {
            LOGGER.warn("Authentication has failed because LDAP password policy handling strategy [{}] cannot handle [{}].",
                response, passwordPolicyHandlingStrategy.getClass().getSimpleName());
            throw new FailedLoginException("Invalid credentials");
        }
        LOGGER.debug("Attempting to examine and handle LDAP password policy via [{}]",
            passwordPolicyHandlingStrategy.getClass().getSimpleName());
        val messageList = passwordPolicyHandlingStrategy.handle(response, getPasswordPolicyConfiguration());
        if (response.isSuccess()) {
            LOGGER.debug("LDAP response returned a result [{}], creating the final LDAP principal", response.getLdapEntry());
            val principal = createPrincipal(upc.getUsername(), response.getLdapEntry());
            return createHandlerResult(upc, principal, messageList);
        }
        if (AuthenticationResultCode.DN_RESOLUTION_FAILURE == response.getAuthenticationResultCode()) {
            LOGGER.warn("DN resolution failed. [{}]", response.getDiagnosticMessage());
            throw new AccountNotFoundException(upc.getUsername() + " not found.");
        }
        throw new FailedLoginException("Invalid credentials");
    }

    /**
     * Creates a CAS principal with attributes if the LDAP entry contains principal attributes.
     *
     * @param username  Username that was successfully authenticated which is used for principal ID when principal id is not specified.
     * @param ldapEntry LDAP entry that may contain principal attributes.
     * @return Principal if the LDAP entry contains at least a principal ID attribute value.
     * @throws LoginException On security policy errors related to principal creation.
     */
    protected @Nullable Principal createPrincipal(final String username, final LdapEntry ldapEntry) throws Throwable {
        LOGGER.debug("Creating LDAP principal for [{}] based on [{}] and attributes [{}]", username, ldapEntry.getDn(),
            ldapEntry.getAttributeNames());
        val id = getLdapPrincipalIdentifier(username, ldapEntry);
        LOGGER.debug("LDAP principal identifier created is [{}]", id);

View on GitHub (pinned to e7288fc434)