apache/druid · warning · BasicSecurityAuthenticationException

Unauthorized

Error message

Unauthorized

What it means

Thrown as BasicSecurityAuthenticationException when the supplied password fails LDAP binding/validation for the user's DN (validatePassword returned false). It maps to the generic 'Unauthorized' message (Access.DEFAULT_ERROR_MESSAGE) so no credential detail leaks. The authentication result is a failure delivered to the authenticator chain.

Source

Thrown at extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authentication/validator/LDAPCredentialsValidator.java:206

          try {
            dirContext.close();
          }
          catch (Exception ignored) {
            // ignored
          }
        }
      }
      catch (NamingException e) {
        LOG.error(e, "Exception during user lookup");
        return null;
      }
      finally {
        Thread.currentThread().setContextClassLoader(currentClassLoader);
      }

      if (!validatePassword(this.ldapConfig, userDn, password)) {
        LOG.debug("Password incorrect for LDAP user %s", username);
        throw new BasicSecurityAuthenticationException(Access.DEFAULT_ERROR_MESSAGE);
      }

      if (this.ldapConfig.isGroupSearchConfigured() && !hasMemberOfAttribute(userResult)) {
        enrichWithGroupSearch(userResult);
      }

      byte[] salt = BasicAuthUtils.generateSalt();
      byte[] hash = hashGenerator.getOrComputePasswordHash(password, salt, this.ldapConfig.getCredentialIterations());
      LdapUserPrincipal newPrincipal = new LdapUserPrincipal(
          username,
          new BasicAuthenticatorCredentials(salt, hash, this.ldapConfig.getCredentialIterations()),
          userResult
      );

      this.cache.put(username, newPrincipal);
      contextMap.put(BasicAuthUtils.SEARCH_RESULT_CONTEXT_KEY, userResult);
    }
    return new AuthenticationResult(username, authorizerName, authenticatorName, contextMap);

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Verify the username/password combination directly against the LDAP directory (e.g. ldapwhoami)
  2. Check the LDAP authenticator config (url, baseDn, userSearch, filters) resolves the correct user DN
  3. Ensure clients are sending updated credentials after password changes
  4. Check coordinator/overlord logs (debug level) for 'Password incorrect for LDAP user' to distinguish wrong password from config errors

Example fix

// before
// auth fails with generic Unauthorized, no diagnostics
// after
// enable debug logging to confirm wrong-password vs DN-resolution issues
log4j.logger.org.apache.druid.security.basic.authentication.validator.LDAPCredentialsValidator=DEBUG
Defensive patterns

Strategy: try-catch

Validate before calling

// cannot pre-validate a password, but verify LDAP connectivity/config first
// ensure the authenticator config resolves the user DN, e.g. run ldapwhoami with the same bind params

Try / catch

try {
  AuthenticationResult result = authenticator.authenticate(request, username, password);
} catch (BasicSecurityAuthenticationException e) {
  // Access.DEFAULT_ERROR_MESSAGE 'Unauthorized': wrong password or bad LDAP config
  auditLog.warn("LDAP auth failed for user " + username);
}

Prevention

When it happens

Trigger: Calling validateCredentials (via the basic LDAP authenticator during HTTP authentication) with a password that does not match the LDAP directory entry for the resolved user DN.

Common situations: Wrong password typed by the user or sent by a misconfigured client; LDAP bind account/config (url, baseDn, userSearch) resolving to the wrong DN; password recently changed in LDAP and cached credentials still in use; case or whitespace issues in the supplied credentials.

Understand the failure class

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/bb74febc98ad5fa5. Report an issue: GitHub.