7

I am writing a webApp with Play2 for Java and want to use LDAP for user authentication... Im new to LDAP and actually don't know exactly how it works and how to use it in Play...

for now I've found this plugin that should probably do the trick, but I cannot find any example of it that uses LDAP authentication. do you know any tutorial that might help me take the first steps?

I also came across this blog post which is looking good, but does not use play authentication plugins, so it might not be that flexible? http://www.philipp.haussleiter.de/2013/07/adding-ldap-authentication-to-a-play-2-application/

behzad
  • 965
  • 11
  • 24

1 Answers1

5

I have an example to authenticate user using LDAP and the play framework. Here is the code hope this will help

public class ActiveDirectoryServices {

  public static final String ldapURL = Play.application().configuration().getString("ActiveDirectory.url");
  public static final String domainName =   Play.application().configuration().getString("ActoveDirectory.DomainName");
  public static final int timeout =         Play.application().configuration().getInt("ActoveDirectory.timeout");

  public static Promise<Boolean> authenticate(String username, String password) throws AuthenticationException, CommunicationException, NamingException{

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

     env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
     env.put("com.sun.jndi.ldap.connect.timeout", ""+(timeout*1000));
     env.put(Context.PROVIDER_URL, ldapURL);
     env.put(Context.SECURITY_AUTHENTICATION, "simple");
     env.put(Context.SECURITY_PRINCIPAL, username+domainName);
     env.put(Context.SECURITY_CREDENTIALS, password);

     DirContext authContext = null; 
     authContext = new InitialDirContext(env);        
     return Promise.pure(Boolean.TRUE);                         
   }

}

Then in a controller I use the above code as following:

try {

    Promise<Boolean> promiseActiveDirectoryCheck = ActiveDirectoryServices.authenticate(userName, password);
      return promiseActiveDirectoryCheck.flatMap(response -> {

      if(response){                           
        return Promise.pure(ok("access granted"));
      }


  });

}catch (AuthenticationException exp) {
  return Promise.pure(ok("access denied"));

}catch (CommunicationException exp) {
  return Promise.pure(ok("The active directory server is not reachable"));

}catch (NamingException exp) {
  return Promise.pure(ok("active directory domain name does not exist"));

}
Ubaidah
  • 897
  • 1
  • 11
  • 26
  • Thanks a lot, I will try it next week and will keep you informed – behzad Sep 10 '15 at 09:05
  • what is the value for domainName ? – behzad Dec 29 '15 at 21:46
  • @behzad it is the domain name you use in your active directory setup. for example it could be "foo.com" or "mycompany.ca" – Ubaidah Dec 30 '15 at 00:50
  • What about the two static final strings account and pass ? What are they used for? – SysHex Feb 26 '16 at 15:23
  • @SysHex, I extracted the code above from a more complex application. You do not need them. I used them in other methods in the class but not in authenticate method. I will remove them from the answer thank you! – Ubaidah Feb 26 '16 at 18:41
  • @Ubaidah Hi! I have another question, would you please explain to me, why you are using promise ? and why do you use flat map? – behzad Nov 17 '17 at 08:30
  • @behzad well I think this code is obsolete for the current release of Play. This was before Java8 :). Play App is a single thread server, LDAP does not provide async calls, So I did not want to block the entire app and I guess I needed flatmap to map the result of the promise. – Ubaidah Nov 17 '17 at 11:18
  • @Ubaidah Thanks for the reply, correct me if I am wrong, InitialDirContext is a sync call, so it will block Play app until results are back, and then you make a promise. I dont have much experience with async coding but in this example, I think the promise does not affect the code. It would be nice if you could help me understand it – behzad Nov 17 '17 at 11:35
  • @behzad https://stackoverflow.com/questions/30739043/async-ldap-authentication-with-play-framework (see this question and the comment) – Ubaidah Nov 17 '17 at 17:31
  • 1
    @Ubaidah Hi! I just checked it with a Thread.sleep and it proved my point. you run InitialDirContext in your main Thread, and it is the function that can block your code. so if I put a Thread.sleep before "return Promise.pure(Boolean.TRUE); " , it still blocks the execution. so this code is not async. :) – behzad Nov 20 '17 at 09:22
  • @behzad How did you know it blocks the execution? you will need to another client to call another API e.g. x and if x is blocked for this different user then the enter app is blocked. I also suggest that you consider using another thread pool https://www.playframework.com/documentation/2.6.x/ThreadPools – Ubaidah Nov 20 '17 at 20:16