LDAP: How to authenticate user with connection details
Asked Answered
O

4

10

I am not able to authenticate a user using LDAP. I have got following details:

URL=ldap://10.10.10.10:389 
LDAP BASE:DC=lab2,DC=ins 
LDAP Bind Account: CN=Ldap Bind,OU=Service Accounts,OU=TECH,DC=lab2,DC=ins 
LDAP Bind Account Pw: secret 

I can search a sAMAccountName value using above details, but how to authenticate a user with user name and password?
If you follow my previous questions then you will understand that, I am successfully able to connect to LDAP server but not able to authenticate him.
User to authenticate:

user: someusername
password: somepwd

I am not able to connect to LDAP server with 'somepwd' and how should I use someusername. I am able to search given user as sAMAccountName.

Openandshut answered 28/8, 2012 at 16:52 Comment(4)
do you have the correct password? does it work using a client like JXplorer ?Lorient
@DmitryB I am able to connect to server with 'secret' but not with 'somepwd'.Openandshut
Then where and how should I use given input user password? In this case 'somepwd'.Openandshut
If I'm understanding your question, you want to use LdapTemplate.authenticate(). Or is your problem in creating the LDAP context in the first place?Mortar
S
24

This is a mashup of stuff I found in various places. It should put you along the correct path if you don't want to use the UnboundID SDK. This isn't production quality, you might want to add the SSL stuff in here if your shop supports it.

public static Boolean validateLogin(String userName, String userPassword) {
    Hashtable<String, String> env = new Hashtable<String, String>();


    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://" + LDAP_SERVER + ":" + LDAP_SERVER_PORT + "/" + LDAP_BASE_DN);

    // To get rid of the PartialResultException when using Active Directory
    env.put(Context.REFERRAL, "follow");

    // Needed for the Bind (User Authorized to Query the LDAP server) 
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_PRINCIPAL, LDAP_BIND_DN);
    env.put(Context.SECURITY_CREDENTIALS, LDAP_BIND_PASSWORD);

    DirContext ctx;
    try {
       ctx = new InitialDirContext(env);
    } catch (NamingException e) {
       throw new RuntimeException(e);
    }

    NamingEnumeration<SearchResult> results = null;

    try {
       SearchControls controls = new SearchControls();
       controls.setSearchScope(SearchControls.SUBTREE_SCOPE); // Search Entire Subtree
       controls.setCountLimit(1);   //Sets the maximum number of entries to be returned as a result of the search
       controls.setTimeLimit(5000); // Sets the time limit of these SearchControls in milliseconds

       String searchString = "(&(objectCategory=user)(sAMAccountName=" + userName + "))";

       results = ctx.search("", searchString, controls);

       if (results.hasMore()) {

           SearchResult result = (SearchResult) results.next();
           Attributes attrs = result.getAttributes();
           Attribute dnAttr = attrs.get("distinguishedName");
           String dn = (String) dnAttr.get();

           // User Exists, Validate the Password

           env.put(Context.SECURITY_PRINCIPAL, dn);
           env.put(Context.SECURITY_CREDENTIALS, userPassword);

           new InitialDirContext(env); // Exception will be thrown on Invalid case
           return true;
       } 
       else 
           return false;

    } catch (AuthenticationException e) { // Invalid Login

        return false;
    } catch (NameNotFoundException e) { // The base context was not found.

        return false;
    } catch (SizeLimitExceededException e) {
        throw new RuntimeException("LDAP Query Limit Exceeded, adjust the query to bring back less records", e);
    } catch (NamingException e) {
       throw new RuntimeException(e);
    } finally {

       if (results != null) {
          try { results.close(); } catch (Exception e) { /* Do Nothing */ }
       }

       if (ctx != null) {
          try { ctx.close(); } catch (Exception e) { /* Do Nothing */ }
       }
    }
}
Savill answered 28/8, 2012 at 18:55 Comment(3)
this is the best solution I have seen so far, I was specifically looking for authenticating an user after binding to LDAP server.Orlena
Is this safe to use with connection pooling?Tusk
This code is great and helped me out a lot. One thing I will mention is that we had to set a base DN to search from, replacing the empty string as the first parameter of ctx.search with our base DN. I suspect nowadays you almost have to do this for any LDAP provider, so just be aware of that when using this code.Minivet
B
8

An LDAP connection starts off as anonymous. To change the authorization state of a connection, use the BIND request. The BIND request takes two forms, 'simple' or 'SASL'. The 'simple' BIND request takes a distinguished name and password. The BIND request should be transmitted over a secure connection, or a non-secure connection promoted to a secure connection using the StartTLS extended request.

Using the UnboundID LDAP SDK:

// exception handling not shown
LDAPConnection ldapConnection = new LDAPConnection(hostname,port);
BindRequest bindRequest = new SimpleBindRequest(username,password);
BindResult bindResult = ldapConnection.bind(bindRequest);
if(bindResult.getResultCode().equals(ResultCode.SUCCESS)) {
   /// successful authentication
}
ldapConnection.close();
Balliol answered 28/8, 2012 at 17:15 Comment(2)
I can not use UnboundID LDAP SDK due to client's restrictions. Is any other way to achieve it?Openandshut
For the constructor of SimpleBindRequest you should give the DN. Not the username.Griseldagriseldis
T
1

We have several JNDI Samples That might help.

The BasicJNDISearch.java is about as basic as you can get and uses command line inputs.

public BasicJNDISearch(String[] args)
{
super();

try
{
    BasicJNDISearch.doBasicSearch(args);
}
catch (Exception ex)
{
    ex.printStackTrace();
}
}

/**
 * 
 * @param stid
 *            String - Standard ID (uid)
 * @throws Exception
 *             -
 */
public static void doBasicSearch(String[] args) throws Exception
{
System.out.println("Performing LDAP Search with:");
System.out.println("    ldapHostName = " + args[0]);
System.out.println("        ldapPort = " + args[1]);
System.out.println("          bindDn = " + args[2]);
System.out.println("       bindDnPwd = " + args[3]);
System.out.println("      searchBase = " + args[4]);
System.out.println("          filter = (" + args[5] + "=" + args[6] + ")");
System.out.println("          Scope: = SUBTREE_SCOPE");

DirContext ctx = getDirContext(args[0], args[1], args[2], args[3]);
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
// ignore attribute name case
// matchAttrs.put(new BasicAttribute(args[5], args[6]));
String filter = "(" + args[5] + "=" + args[6] + ")";
// Search for objects with those matching attributes
NamingEnumeration<?> answer = ctx.search(args[4], filter, constraints);
formatResults(answer);
ctx.close();
}
Tyrolienne answered 30/8, 2012 at 10:26 Comment(0)
F
0

Try using this, it worked for me

public static Boolean validateLogin(String userName, String userPassword) {
    Hashtable<String, String> env = new Hashtable<String, String>();


    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://" + LDAP_SERVER + ":" + LDAP_SERVER_PORT + "/" + LDAP_BASE_DN);
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_PRINCIPAL, userName + "@" + LDAP_SERVER);
    env.put(Context.SECURITY_CREDENTIALS, userPassword);

    DirContext ctx;
    try {
       ctx = new InitialDirContext(env); //throw exception, if username-password not correct
       return true;
    } catch (Exception e) {
        return false;
    }
}
Farceuse answered 5/9, 2018 at 7:0 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.