How to query LDAP and authenticate users

I dont have much experience in Java.
Need to write a java app to authenticate users coming into my web page by querying ldap.
I have a login.jsp that accepts username/password, need direction on writing all other classes to authenticate users and display authenticated users username on firstpage.html
Thank you!


makam_75Asked:
Who is Participating?
 
petmagdyCommented:
First u must have a Directory server like active Directory, or Sun One Directory Server or OpenLDAP (openldap is open source), u can download it from www.openldap.org

then here is a sample authenticate function:

import java.util.Hashtable;
import java.util.Enumeration;

import java.util.*;
import java.io.*;
import javax.naming.*;
import javax.naming.directory.*;

  public boolean authenticateUser(String username, String password) throws NamingException
  {
    Hashtable env = new Hashtable(5, 0.75f);

    env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

    /* Specify host and port to use for directory service */
    env.put(Context.PROVIDER_URL, "ldap://LDAP_SERVER:389");

    env.put(Context.SECURITY_AUTHENTICATION, Simple);
    env.put(Context.SECURITY_PRINCIPAL, "uid=" +username +", ou=users,o=myOrganization, dc=mydomain,dc=com");
    env.put(Context.SECURITY_CREDENTIALS, password);

    try
    {
        /* get a handle to an Initial DirContext */
        DirContext ctx = new InitialDirContext(env);

            //Authenticated
        return true;
    }
    catch (javax.naming.AuthenticationException ae)
    {
      //Authentication failure
        return false;
    }
    catch (NamingException e)
    {
      return false;
    }
  }
0
 
CEHJCommented:
What container are you using?
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

 
makam_75Author Commented:
SunOne is the webserver. I was looking for sample code.
Thanks.
0
 
CEHJCommented:
>>I was looking for sample code

This kind of thing should in theory require little code since the functionality is provided declaratively. It will be more a question of putting together the right config files for your container
0
 
petmagdyCommented:
just a little correction to my code:

this line:
  env.put(Context.SECURITY_AUTHENTICATION, Simple);

is offcourse meant to be:

  env.put(Context.SECURITY_AUTHENTICATION, "simple");
0
 
CEHJCommented:
>>then here is a sample authenticate function:

That's not really right. All that context related stuff should have been set up before authentication is attempted. An authenticate function should really only get the context and do a lookup
0
 
petmagdyCommented:
CHEJ

this is how to do LDAP programatic authentication, I meant to provide a sample not exact function implementation, althought this is code is right if the users are located at the orgainzation unit: ou=users,o=myOrganization, dc=mydomain,dc=com,

I am not refering to the Decalarative or JAAS way
0
 
CEHJCommented:
>>this is how to do LDAP programatic authentication

Even then it's looking a bit iffy for the reasons i've given - the environment should already be there - even if it was done programmatically

>>am not refering to the Decalarative or JAAS way

The idea is to let the container do as much work as possible, declaratively. Such programmatic code that there is will simply input the credentials and receive the result
0
 
makam_75Author Commented:
Hello petmagdy.
Not sure the need for setting up a directory server.
I already have LDAP set up in my company. Eg. If I telnet to any m/c in the network, I am able to run an ldapsearch command. Does this mean the above code will compile as is?

Or do you mean to say I need to have my own instance of directory server running on the host were I have my web page that authenticates users? Guess I am not clear on it because I do not have understanding of the whole picture.

Like I mentioned before, I am new to this, so I will be using any code as is. I do have my organization unit as ou=users,o=myOrganization, dc=mydomain,dc=com. Please let me know if there are any other concerns.
Thankyou!
0
 
CEHJCommented:
You need to configure the app server to use the existing LDAP. See the container docs
0
 
petmagdyCommented:
CHEJ
I am not in favorate of dwelling arround a point
when refering to the programatic LDAP authenitcation the statment u say

>> An authenticate function should really only get the context and do a lookup

This statment is not accurate Authentication is not lookup on the user in LDAP, it is challenging the User/Password againist the Directory server this achieved by 2 ways:

First way: lookup on the user object in the DS and if found use the DS irreversable encryption technique to decrypt the password and validate it againist the savied in database

Second way: get an LDAP context if success then the user is authented as I provided in the sample code

bye the way Active directory only accepts the second way
0
 
petmagdyCommented:
no I meant to use an existing available Directory server (LDAP server), so u provide the Host name of this server in the LDAP url (ldap://servername:389)

But if the organization will not allow u to test on its running Production LDAP server u can easly make ur own instance on ur machine
0
 
CEHJCommented:
>>This statment is not accurate Authentication is not lookup on the user in LDAP

>>First way: lookup on the user object in the DS and if found ...

?

makam_75, petmagdy's is a way of doing this programmatically although i'm not convinced it's the best way
0
 
petmagdyCommented:
CEHJ,

I know Recently JAAS became the best way to implement J2EE application security, but as a first step for makam to understand the foundation of this is to concentrate on JNDI and LDAP concepts first that is better before going for more advanced techniques

By the way not all cases the decalrative is the best, in one of the projects I was involved in, when users in a single ou reached more than 60K users declarative costs 4 minutes to authenticate the user while programatic did it in 3 seconds

cheers ;)
0
 
makam_75Author Commented:
Hi all,
I am not looking for the most correct solution for any generic app. I have a small and urgent requirement, and want to get to it in a most efficient time frame. As long as it works and no cons associated with the method, I am ok in hardcoding some data.  
Petmagdy,
I will have to find out the ldap server name (production and test) from our admin. Are there any other questions I should be asking? If you know a beginners guide for ldap, can youpass it on to me too.

Appreciate everyones time and help here. Thank you.

0
 
CEHJCommented:
If you're into getting something running quickly, use petmadgy's suggestion.

>>As long as it works and no cons associated with the method

I'll let petmadgy tell you about the pros and cons ;-)
0
 
petmagdyCommented:
do u have a user/password on this directory server?
if no u need to get one for testing purposes, also u need to know for the users to be authenticated where r they on the Directory server hierarchy for example, their location on active directory maybe something like this:

cn=users, dc=thedomain, dc=com

if other may be look like this:

ou=users, o=orgainizationName, dc=thedomain, dc=com

and the heirarchy can be more complicated than that
0
 
petmagdyCommented:
No CHEJ, I am sure that u always has the best way ;)
0
 
makam_75Author Commented:
Thanks, I will try and implement this today. will let you know the status by mid day tomorrow. I hope you automatically get notification to updates to this thread.
0
 
CEHJCommented:
We do ;-)
0
 
makam_75Author Commented:
OK I am getting much earlier.

On command line, a command like this works for me
ldapserach -h "directory.tw.com" -b "ou=people,o=tw.com" "uid=makam"
(So I know that directory name and heirarchy structure are correct. )

So, I tried to implement like this. I hardcoded the userid/password I use to login to our intranet(that they have set up using nsconfig) But get the message "false" which means I was not succesffuly authenticated.

Could it be that the password is stored as encrypted, and the one I am passing is not and so they are not matching?

public class myLDAPProg{
      public myLDAPProg() {
      }
      
      public static void main( String args[]) {
            queryLDAP q = new queryLDAP();
            try {
                        boolean value=q.doAuthenticate("myname","mypass");
                        System.out.println("val is"+ value);
            }
            catch(NamingException e) {}
      }
      
}

      public class queryLDAP{
            public queryLDAP(){
            }
            
            public boolean doAuthenticate(String username, String password) throws NamingException
              {
                  Hashtable env = new Hashtable(5, 0.75f);

                  env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

                  /* Specify host and port to use for directory service */
                  env.put(Context.PROVIDER_URL, "ldap://directory.tw.com:389");

                  env.put(Context.SECURITY_AUTHENTICATION, "simple");
                  env.put(Context.SECURITY_PRINCIPAL, "uid=" +username +", ou=people,o=tw.com,");
                  env.put(Context.SECURITY_CREDENTIALS, password);

                  try
                  {
                        /* get a handle to an Initial DirContext */
                        DirContext ctx = new InitialDirContext(env);

                          //Authenticated
                        return true;
                  }
                  catch (javax.naming.AuthenticationException ae)
                  {
                    //Authentication failure
                     return false;
                  }
                  catch (NamingException e)
                  {
                    return false;
                  }
              }
             
      }

0
 
petmagdyCommented:
no u don't need to do thing about the password


1- Please make sure that in ur class path u have the following jars:

jndi.jar
ldap.jar
ldapbp.jar
providerutil.jar

also if still return false please put in the catch exceptions

e.printStackTrace()
0
 
makam_75Author Commented:
If i did not have the jar files, it would not run, correct?

Anyway , I run the program on command line. I could not locate these jar files under C:\j2sdk1.4.2_06\jre\lib

Also, this does not compile
catch(NamingException e) {
                  System.out.println(e.printStackTrace());
            }
The error is The method println() in the type PrintStream is not applicable for the arguments (void)
0
 
CEHJCommented:
>>I could not locate these jar files under C:\j2sdk1.4.2_06\jre\lib

They won't be there. You need to install J2EE SDK too.

>>
catch(NamingException e) {
               System.out.println(e.printStackTrace());
          }
>>

should be

catch(NamingException e) {
    e.printStackTrace();
}
0
 
CEHJCommented:
>>You need to install J2EE SDK too.

In fact they may not all be there either. petmagdy will probably know where they all are
0
 
makam_75Author Commented:
But I am getting a "false" as the output. So it was able to get hold of all jar files is my thinking...
0
 
makam_75Author Commented:
Thanks, I did  e.printStackTrace(); , but do not see any change in the output.
My o/p is
val isfalse

0
 
makam_75Author Commented:
Sorry, here is the exception.
javax.naming.InvalidNameException: [LDAP: error code 34 - Invalid DN]
        at com.sun.jndi.ldap.LdapCtx.processReturnCode(Unknown Source)
        at com.sun.jndi.ldap.LdapCtx.processReturnCode(Unknown Source)
        at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
        at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source)
        at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
        at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
        at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
        at javax.naming.InitialContext.init(Unknown Source)
        at javax.naming.InitialContext.<init>(Unknown Source)
        at javax.naming.directory.InitialDirContext.<init>(Unknown Source)
        at com.synopsys.ldap.queryLDAP.doAuthenticate(queryLDAP.java:44)
        at com.synopsys.ldap.authenticateUser.main(authenticateUser.java:40)
val isfalse

I had'nt recreated the jar file before.
0
 
CEHJCommented:
>>So it was able to get hold of all jar files is my thinking...

Well if it now compiles and runs, then yes ;-)

You'll have to check the directory / your credentials if you're getting an unexpected negative
0
 
makam_75Author Commented:
OK there was one extra comma, I removed it and it is working!
Hurray!
0
 
CEHJCommented:
Good ;-)
0
 
CEHJCommented:
So my contribution to that was worth 0 points then makam_75?
0
 
petmagdyCommented:
LOOOLLLLL, MAKAM sorry I went to bed during the last comments, time zone difference :)
I think MAKAM, it is time to get also idea about the declarative way of LDAP authentication, I sure CEHJ will help u great deal on that ;)
0
 
makam_75Author Commented:
CEHJ,
I did value your comments very much!
The reasoning behind my awarding points was I have taken the code from petmagdy "as is" and it is working as a complete solution to the question i listed. so i thought it will not be fair if i dont assign him the complete points.
I appreciate your response. Thanks.

0
 
CEHJCommented:
>>"as is" and it is working as a complete solution to the question i listed

Err.. apart from the fact that you would not have been able to compile it without my help to the question containing the following:

>>Also, this does not compile
0
 
makam_75Author Commented:
Sorry I overlooked that. I will remember to be more cautius while assigning points in future.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.