Enterprise Java

2 Ways to Setup 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 projects, we need to authenticate against active directory using LDAP by credentials provided in the login screen. Sometimes 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 of it’s my preferred Java framework for authentication, authorization, and security related stuff.

We can do the same thing in Java by writing ower own program for doing LDAP search and then 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 features which are required by enterprise Java application including SSL Security, encryption of passwords and session timeout facilities.

1. 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 the 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 the 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 the LDAP server.
Search – LDAP search is an operation which is performed to retrieve Dn of the 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 a 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.

2. LDAP Authentication in Active Directory Spring Security

There are two ways to implement active directory authentication using LDAP protocol in spring security, the first way is a programmatic and declarative way which requires some coding and some configuration.

On the other hand, the second cond way is an out of box solution from spring security which just requires configuring ActireDirectoryAuthenticationProvider and you are done. we will see both approaches but I suggest using the second one because of its simplicity and easy to use a feature.

2.1 Active Directory Authentication using LDAP in Spring Security -Example 1

Configuration
Add the following configuration into your spring application-context.xml file, I would suggest putting this configuration in a separate application-context-security.XML file along with other security-related stuff.
1) Configuring LDAP Server
In order to configure LDAP server, please put following XML snippet into Spring security configuration file:

<s:ldap-server 
  url="ldap://stockmarket.com"   //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 the active directory or any other LDAP directory is performed in two steps first an LDAP search is performed to locate Dn(Distinguished Name) of the user and then this Dn is used to perform LDAP Bind.

If the bind is successful than user authentication is successful otherwise it fails. Some people prefer remote compare of password than LDAP bind, but LDAP bind is what you mostly end of doing.

Most of the 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 herein manager-in and manager-password.property.
In Summary, now LDAP login will be done in these steps:

  1. Your Service or application bind itself with LDAP using manager-dn and manager-password.
  2. LDAP search for the user to find UserDn
  3. LDAP bind using UserDn

That’s complete the LDAP login part. Now, let’s move to next part of configuration LDAP authentication provider.
2) Configuring LDAP Authentication Provider
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.

<s:authentication-manager erase-credentials="true">
<s:ldap-authentication-provider
   user-search-base="dc=stockmarketindia,dc=trader"
   user-search-filter="userPrincipalName={0}"
/>

<s:authentication-provider 
  ref="springOutOfBoxActiveDirecotryAuthenticationProvider"/>
</s:authentication-manager>

Now a small piece of coding is needed to pass the userPrincipalName and authenticate the 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 the whole day figuring out when my application was repeatedly throwing javax.naming.PartialResultException: Unprocessed Continuation Reference(s) you can also use sAMAccountName for the searching user, both userPrincipalName and sAMAccountName are unique in the Active Directory.

What is most important here is that it has to be full name e.g. name@domain like jimmy@stockmarket.com.

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

2.2 Active Directory Authentication using LDAP in Spring Security – Simpler Example

The second approach is much simpler and cleaner because it comes out of the box, you just need to configure LDAP server URL and domain name and it will work like cream.

<s:authentication-manager erase-credentials="true">
   <s:authentication-provider ref="ldapActiveDirectoryAuthProvider"/>
</s:authentication-manager>

<bean id="ldapActiveDirectoryAuthProvider" 
class="org.springframework.security.ldap.authentication.ad.
                ActiveDirectoryLdapAuthenticationProvider">
  <constructor-arg value="stockmarket.com" />  //your domain
  <constructor-arg value="ldap://stockmarket.com/" />  //ldap url
</bean>

That’s it, done. This configuration will both authenticate and load all the granted authorities from LDAP like a group which you are a member of. This is integrated with spring security login element also.

2.3 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.

If you don’t know how to download Spring framework JAR files, follow the steps given in this Spring Framework JAR download Guide, which explains how to download Spring framework and other related JAR from Maven Central.

2.4 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 their solutions 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 an invalid format of username. it solved by providing full name e.g. jemmy@stockmarket.com

2.5 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 a 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.

2.6 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 it’s not safe.

One solution is to use LDAP( 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 to use “”ldaps://stockmarket.com/“. actually, a port for LDAP is 339 and for LDAPS is 636 but that’s been taken care by spring in the second approach, in the 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

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

To solve this problem you need to add certificates returned by Server into JRE’s keystore. Btw, if you are confused between the key store and trust store then please read my article difference between keystore and trust store in Java to first learn about it.

2. 7 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 on 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, the certificate is already trusted

We are done, now if you try authenticating against LDAPS you will succeed.

There are many other approaches 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’ll try my best to help you.

Published on Java Code Geeks with permission by Javin Paul, partner at our JCG program. See the original article here: 2 Ways to Setup LDAP Active Directory Authentication in Java Spring Security Example Tutorial

Opinions expressed by Java Code Geeks contributors are their own.

Javin Paul

I have been working in Java, FIX Tutorial and Tibco RV messaging technology from past 7 years. I am interested in writing and meeting people, reading and learning about new subjects.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Erin
4 years ago

How to configure in annotation method? I need to do like auth.ldapAuthentication()

Quan Qiu
Quan Qiu
1 year ago

I have been struggling with LDAP login for days. Is there example code for LDAP login for a spring boot project?

Back to top button