Search code examples
javaactive-directoryldap

LDAP context search in Java provides no results, even when searching on value known to be there


I've done a lot of Googling and seen several similar answers on this site, but nothing is working for me.

I have been trying to do a search of ActiveDirectory using LDAP. The search runs okay, but it never returns results. I am searching on userPrincipalName, and this user absolutely exists in ActiveDirectory.

String securityPrincipal;
    securityPrincipal = "{0}@" +"ourcompany";
    securityPrincipal = MessageFormat.format(securityPrincipal, username);

    Hashtable<String,Object> env = new Hashtable<>();

    env.put(Context.PROVIDER_URL, "ldaps://OURCOMPANY:636");
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    //Internal and external the same
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_PRINCIPAL, securityPrincipal);
    env.put(Context.SECURITY_CREDENTIALS, password);
    env.put(Context.REFERRAL,"follow");

    boolean success;
    LdapContext ldapCtx = null;
    try {
        ldapCtx = new InitialLdapContext(env, null);
        success = true;
    } catch (NamingException ex) {
        ex.printStackTrace();
        success = false;
if(ldapCtx != null){
doSearch(ldapCtx)
}

private static final void doSearch(LdapContext ctx) throws NamingException{
        NamingEnumeration results = null;
        String domain = "DC=ourcompany,DC=com";
    String organizationalUnit = "ou=external";

    String searchUser;
    searchUser = "[email protected]";
    try {
        DirContext schema = ctx.getSchema("");

        String[] returning = {"userPrincipalName"};
        SearchControls ctrls = new SearchControls();
        ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        ctrls.setReturningAttributes(returning);
        Attributes attributes = new BasicAttributes(true);
        attributes.put("userPrincipalName",searchUser);

         results = ctx.search(organizationalUnit +"," +domain,attributes);

        while (results.hasMoreElements()){
            System.out.println("...");
        }


        System.out.println(results.hasMore());


    }catch (NamingException ex){
        ex.printStackTrace();
    } finally {
        results.close();
    }

In addition to what is above, I've tried:

  • Using this type of search: results = ctx.search(organizationalUnit +"," +domain,"(& (userPrincipalName=" +searchUser +"))",ctrls);
  • Using this type of search: results = ctx.search(domain,"(& (userPrincipalName=" +searchUser +"))",ctrls);
  • Passing null to ctrls.setReturningAttributes()
  • ctrls.setSearchScope(SearchControls.OBJECT_SCOPE);

This should be returning results. Results is not null, but results.entries() is empty.


Solution

  • Since AD is a Microsoft tool, its responses are not driven to help. Are driven to be impossible to understand and to require a payed support. Here a response sample if you are sending something that AD don't understand or support. It is so complex to figure out the error reason/cause.

    [LDAP: error code 16 - 000016515: LdapErr: DSID-066675D87, data 0, v64xyz]
    

    Context object location is millimeter

    You need to find the exact context object or location in which your user exist.

    enter image description here

    image source: https://www.informit.com/articles/article.aspx?p=101405&seqNum=7

    option #1

    What helped me was to access to the AD Admin GUI and put the mouse over the user and then a popup will appear with the exact context of this object. Also at the top of ui appear the required context. If user don't exist, create a new one.

    enter image description here

    option #2

    Also you can obtain the same value using the Distinguished attribute, editing the user as Admin

    enter image description here

    Source: https://windowstechno.com/how-to-check-the-distinguished-name-dn/

    Tip

    Just to try, you could design a request with these values:

    Field Sample Value
    objectLocation OU=users,DC=foo,DC=bar,etc=wtf
    searchQuery ([email protected])

    And I use these values in my code:

    LdapContext ctx = new InitialLdapContext(environment, null);
    ctx.setRequestControls(null);
    NamingEnumeration<?> searchResultEnum =
      ctx.search(objectLocation, searchQuery, getSimpleSearchControls());
    

    This will help you to try dozens of combinations until you find the exact objectLocation