function validateAuthData(authData, options) {
  if (!optionsAreValid(options)) {
    return new Promise((_, reject) => {
      reject(
        new Parse.Error(
          Parse.Error.INTERNAL_SERVER_ERROR,
          'LDAP auth configuration missing'
        )
      );
    });
  }
  const clientOptions = (options.url.startsWith("ldaps://")) ?
    { url: options.url, tlsOptions: options.tlsOptions } : { url: options.url };

  const client = ldapjs.createClient(clientOptions);
  const userCn =
    typeof options.dn === 'string'
      ? options.dn.replace('{{id}}', authData.id)
      : `uid=${authData.id},${options.suffix}`;

  return new Promise((resolve, reject) => {
    client.bind(userCn, authData.password, ldapError => {
      delete(authData.password);
      if (ldapError) {
        let error;
        switch (ldapError.code) {
          case 49:
            error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAP: Wrong username or password');
            break;
          case "DEPTH_ZERO_SELF_SIGNED_CERT":
            error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAPS: Certificate mismatch');
            break;
          default:
            error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAP: Somthing went wrong (' + ldapError.code + ')');
        }
        reject(error);
        client.destroy(ldapError);
        return;
      }

      if (
        typeof options.groupCn === 'string' &&
        typeof options.groupFilter === 'string'
      ) {
        searchForGroup(client, options, authData.id, resolve, reject);
      } else {
        client.unbind();
        client.destroy();
        resolve();
      }
    });
  });
}
The application stores sensitive information in cleartext within a resource that might be accessible to another control sphere.