Sabtu, 15 Maret 2014

LDAP Active Directory Authentication in Java Spring Security Example Tutorial


LDAP authentication is one of the most popular authentication mechanism around the world for enterprise application and Active directory (an LDAP implementation by Microsoft for Windows) is another widely used ldap server. In many project we need to authenticate against active directory using ldap by credentials provided in login screen. Some time this simple task gets tricky because of various issues faced during implementation and integration and no standard way of doing ldap authentication. Java provides ldap support but in this article I will mostly talk about spring security because its my preferred Java framework for authentication, authorization and security related stuff. you can do same thing in Java by writing your own program for doing LDAP search and than LDAP bind but as I said its much easier and cleaner when you use spring security for LDAP authentication.

Along with LDAP Support, Spring Security also provides several other feature which is required by enterprise java application including SSL Security, encryption of passwords and session timeout facilities.

LDAP Authentication Basics

Before getting deep into LDAP authentication on Active Directory, let's get familiar with some LDAP term because most of the time user is doing it first time and they are not very familiar with typical LDAP glossary such as Dn , Ou , Bind or search etc.


Dn - Distinguished name, a unique name which is used to find user in LDAP server e.g. Microsoft Active Directory.


Ou - Organization Unit


Bind - LDAP Bind is an operation in which ldap clients sends bindRequest to ldap user including username and password and if LDAP server able to find user and password correct, it allows access to ldap server.


Search - LDAP search is an operation which is performed to retrieve Dn of user by using some user credential.


Root - LDAP directory's top element, like Root of a tree.


BaseDn - a branch in LDAP tree which can be used as base for ldap search operation e.g. dc=Microsoft,dc=org"


If you want to know more about LDAP check this link it has detailed information on LDAP.


LDAP Authentication Active Directory Spring

Active Directory Authentication in Spring Security



ldap authentication active directory spring
There are two ways to implement active directory authentication using LDAP protocol in spring security, first way is programmatic and declarative way which requires some coding and some configuration and second way is an out of box solution from spring security which just require to configure ActireDirectoryAuthentication provider and you are done. we will see both approach but I suggest using second one because of its simplicity and easy to use feature.






Active Directory Authentication using LDAP in Spring Security -1



Configuration
Add following configuration into your spring application-context.xml file, I would suggest to put this configuration in a separate application-context-security.xml file along with other security related stuff.


1) Configuring LDAP Server



//ldap url
port="389"                              //ldap port
manager-dn="serviceAcctount@sotckmarket.com" //manager username
manager-password="AD83DgsSe"/>             //manager password


This configuration is self explanatory but briefly few lines about manager-dn and password, Ldap authentication on active directory or any other ldap directory is performed in two steps first an LDAP search is performed to locate Dn(Distinguised Name) of user and than this Dn is used to perform LDAP Bind , if bind is successful than usre authentication is successful other wise it fails. Some people prefer remote compare of password  than LDAP bind, but LDAP bind is what you mostly end of doing. most of Active directory doesn't allow Anonymous Search operation , so to perform an ldap search your service must have an LDAP account which is what we have provided here in manager-dn and manager-password.


In Summary now LDAP login will be done on these step
1) Your Service or application bind itself with LDAP using manager-dn and manager-password.
2) LDAP search for user to find UserDn
3) LDAP bind using UserDn


2) Configuring LDAP Authentication Provider
user-search-base="dc=stockmarketindia,dc=trader"
user-search-filter="userPrincipalName={0}"
/>


This section specifies various authentication provider in spring-security here you can see your LDAP authentication provider and we are using userPrincipalName to search user inside Microsoft Active directory.


Now small piece of coding to pass userPrincipalName and authenticate user.


public boolean login(String username, String password) {
AndFilter filter = new AndFilter();
ldapTemplate.setIgnorePartialResultException(true); // Active Directory doesn’t transparently handle referrals. This fixes that.


filter.and(new EqualsFilter("userPrincipalName", username));
return ldapTemplate.authenticate("dc=stockmarketindia,dc=trader", filter.toString(), password);
}


line 2 is very important in this program because I spent whole day figuring out when my application was repeatedly throwing javax.naming.PartialResultException: Unprocessed Continuation Reference(s)


you can also use sAMAccountName for searching user, both userPrincipalName and sAMAccountName are unique in Active directory. What is important here is that it has to be full name e.g. name@domain like jimmy@stockmarket.com.


authenticate() method will return true or false based on result of bind operation.


Active Directory Authentication using LDAP in Spring Security - 2

Second approach is much simpler and cleaner because it comes out of box , you just need to configure ldap server url and domain name and it will work like cream.






  //your domain
  //ldap url


Done. This configuration will both authenticate and load all the granted authority from LDAP like group which you are member of. This is integrated with spring security login element also.




Dependency


This example is based on spring security 3.0 and I was using spring-ldap-1.3.1.RELEASE-all.jar and spring-security-ldap-3.1.0.RC3.jar




Errors during LDAP authentication
you need to be very lucky to complete LDAP authentication against Active directory without any error or exception, here I am listing down some common error which I encountered and there solution for quick reference.


1) javax.naming.PartialResultException: Unprocessed Continuation Reference(s); remaining name 'dc=company,dc=com'
This error comes because Microsoft Active Directory doesn't handle referrals properly and to fix this set this property


ldapTemplate.setIgnorePartialResultException(true);


2) javax.naming.NameNotFoundException: [LDAP: error code 32 - No Such Object]; remaining name ''
This error solved with some trial and error and mainly came due to invalid format of username. it solved by providing full name e.g. jemmy@stockmarket.com






Tools


LDAP Browser: Having some tools to look data inside LDAP directory is best it gives you some visibility as well as means to browse data in LDAP. it's called as LDAP browser and there are lot of open source LDAP browser available in web e.g. jexplorer. you can browse and see data inside
Active directory by using LDAP browser.




Ldap Active directory Authentication over SSL

This works perfectly to implement ldap authentication against microsoft active directory. but one thing you might want to put attention is that with ldap username and password travel to ldap server as clear text and anyone who has access to ldap traffic can sniff user credential so its not safe. one solution is to use ldaps( LDAP over ssl) protocol which will encrypt the traffic travels between ldap client and server. this is easy to do in spring-security what you need to change is the url instead of "ldap://stockmarket.com/" you need ot use ""ldaps://stockmarket.com/". actually port for ldap is 339 and for ldaps is 636 but that's been taken care by spring in second approach, in first approach you need to provide this information.


What problem you may face is "unable to find valid certification path to requested target"


exception  as shown below:


javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target




Reason of this Exception is simple, Certificate returns during SSL handshake is not signed by any trustsed Certification Authority(CA) which is configured in you JRE keysotre e.g Verisign, Thwate, goDaddy or entrust etc. Instead Server is sending certificate which is not known to JRE.


To solve this problem you need to add certificates returned by Server into JRE's keystore.




What I did to solve the problem
Nothing surprising , I use an open source program called InstallCert.java , just run with your ldap server and port and it will try to connect LDAP server using SSL and first throw same "PKIX path building failed" and then Certificates returned by LDAP server. It will then ask you to add Certificate into keystore just give certificate number as appeared in your screen and it will then add those certificate into "jssecacerts" inside C:\Program Files\Java\jdk1.6.0\jre\lib\security folder. Now re-run the program that error must be disappeared and


it will print:


"Loading KeyStore jssecacerts...
Opening connection to stockmarket.com:636...
Starting SSL handshake...
No errors, certificate is already trusted


you are done, now if you try authenticating against ldaps you will be succeed.


There are many other approach to perform ldap authentication against active directory even without spring security by using Java. but I found spring-security very helpful so consider using it for your security requirement. let me know if you face any issue during ldap login and I
will try my best to help you.




Other Java Tutorials


Difference between StringBuffer and StringBuilder in Java























Source:http://javarevisited.blogspot.com/2011/11/ldap-authentication-active-directory.html

Tidak ada komentar:

Posting Komentar