prestodb/presto · warning · AccessDeniedException

Invalid credentials

Error message

Invalid credentials

What it means

LdapAuthenticator.authenticate catches javax.naming.AuthenticationException from the LDAP bind and rethrows it as AccessDeniedException("Invalid credentials"). This means the LDAP server explicitly rejected the bind for the supplied user DN/password: a genuine authentication rejection by the directory, surfaced to the client as invalid credentials.

Source

Thrown at presto-password-authenticators/src/main/java/com/facebook/presto/password/ldap/LdapAuthenticator.java:115

    private Principal authenticate(Credentials credentials)
    {
        return authenticate(credentials.getUser(), credentials.getPassword());
    }

    private Principal authenticate(String user, String password)
    {
        Map<String, String> environment = createEnvironment(user, password);
        DirContext context = null;
        try {
            context = createDirContext(environment);
            checkForGroupMembership(user, context);

            log.debug("Authentication successful for user [%s]", user);
            return new BasicPrincipal(user);
        }
        catch (AuthenticationException e) {
            log.debug("Authentication failed for user [%s]: %s", user, e.getMessage());
            throw new AccessDeniedException("Invalid credentials");
        }
        catch (NamingException e) {
            log.debug(e, "Authentication error for user [%s]", user);
            throw new RuntimeException("Authentication error");
        }
        finally {
            if (context != null) {
                closeContext(context);
            }
        }
    }

    private Map<String, String> createEnvironment(String user, String password)
    {
        return ImmutableMap.<String, String>builder()
                .putAll(basicEnvironment)
                .put(SECURITY_AUTHENTICATION, "simple")
                .put(SECURITY_PRINCIPAL, createPrincipal(user))

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Verify the client's password by binding manually (ldapwhoami -x -H ldaps://... -D <userDn> -W)
  2. Check the user-bind-pattern produces the correct DN; test the exact DN with ldapsearch
  3. Confirm the user account is active (not locked/expired) and under the expected base DN
  4. Enable debug logging to see the user DN used and the server's rejection reason

Example fix

// before
presto.ldap.user-bind-pattern=${USER}@example.com  // wrong form for this directory
// after
presto.ldap.user-bind-pattern=uid=${USER},ou=people,dc=example,dc=com
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the bind works before pointing the coordinator at it:
// ldapwhoami -x -H ldaps://ldap.example.com:636 -D 'uid=alice,ou=people,dc=example,dc=com' -W

Try / catch

try {
    return ldapAuthenticator.authenticate(user, password);
} catch (AccessDeniedException e) {
    auditLog.warn("LDAP bind rejected for user {}", user);
    throw new WebApplicationException(Status.UNAUTHORIZED);
}

Prevention

When it happens

Trigger: A client authenticates; the authenticator binds to the LDAP server as the DN built from the user-bind-pattern with the given password; the server returns AuthenticationException (LDAP code 49, invalid credentials).

Common situations: Wrong password on the client; user DN template mismatch so the bind DN is wrong; user missing, disabled, or locked in LDAP; expired password; wrong base DN or replica; special characters in the username breaking DN construction.

Understand the failure class

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/3e00212aba1207d3. Report an issue: GitHub.