Sunday, January 2, 2011

Spring Security - MVC: Using an LDAP Authentication Provider

In this tutorial we will setup a simple Spring MVC 3 application, secured by Spring Security. Our users will be authenticated against an LDAP provider. We'll explore how we can configure an LDAP authentication provider. For this tutorial we will leveraged on our existing tutorials to lessen the repetition of steps. The overall structure of our application will be based on Spring Security 3 - MVC: Using a Simple User-Service Tutorial. This is a good exercise to show how easy we can change providers without disrupting the whole flow of our existing system. The LDAP server and entries will be based on LDAP - Apache Directory Studio: A Basic Tutorial

What is LDAP?
The Lightweight Directory Access Protocol (LDAP) is an application protocol for reading and editing directories over an IP network. A directory is an organized set of records. For example, the telephone directory is an alphabetical list of persons and organizations, with each record having an address and phone number. A directory information tree often follows political, geographic, or organizational boundaries. LDAP directories often use Domain Name System (DNS) names for the highest levels. Deeper inside the directory might appear entries for people, departments, teams, printers, and documents.

Source: http://en.wikipedia.org/wiki/LDAP
If this is your first time to LDAP, you might be wondering how is this different from an RDBMS. I suggest my readers to visit the following article Should I Use a Directory, a Database, or Both?

We'll start immediately with the spring-security.xml configuration.

spring-security.xml

Honestly, this is the only file that you need to change from the Spring Security 3 - MVC: Using a Simple User-Service Tutorial.

Actually, we just deleted a couple of entries. The old configuraiton contains an in-memory user-service provider:

The new configuration contains an LDAP authentication provider:

The real tricky part here is ensuring that you can connect to your LDAP server and ensuring that you've mapped correctly the attribute names from your ldap-authentication-provider to the LDAP Directory Information Tree.

To get a better understanding, let's examine the directory structure of the server. You will gain better insight if you've read first LDAP - Apache Directory Studio: A Basic Tutorial.

Here's server's structure:
mojo
 |
 |--groups
 |    |
 |    |--Admin
 |    |--User
 |
 |--users
      |
      |--guy1
      |--guy2
      |--guy3
      |--guy4
Here's a screenshot of the server's directory:

Let's focus on the elements of the ldap-authentication-provider

The attribute value of the user-search-filter="(uid={0})" corresponds to the attribute we've declared for the users
The {0} in the (uid={0}) will be replaced by the username entered in the form.

The value of the user-search-base="ou=users" corresponds to the attribute we've declared in the directory tree

The attribute value of the group-search-filter="(uniqueMember={0})" corresponds to the attribute we've declared for the groups
The {0} in the (uniqueMember={0}) represents the Distinguished Name (DN) of the user. On our sample data, the dn for Hugo Williams is cn=Hugo Williams,ou=users,o=mojo. The DN is similar with the primary key in relational databases.

The value of the group-search-base="ou=groups" corresponds to the attribute we've declared in the directory tree

The attribute value of the group-role-attribute="cn" corresponds to the attribute we've declared for the groups. Spring Security uses this value of this attribute to determine the authorization level of the user.

The value of the role-prefix="ROLE_" is used to indicate what prefix should be added on the values received from group-role-attribute="cn". If you examine carefully the server's structure, we have two roles declared as cn=Admin and cn=User
The values that will be returned are Admin and User. With role-prefix="ROLE_", they will become ROLE_ADMIN and ROLE_USER respectively.

The LDAP Server
Let's examine ldap-server tag.


The url ldap://localhost:10389/o=mojo is composed of the server's url and port number ldap://localhost:10389/ and the base parent path o=mojo

The attribute manager-dn="uid=admin,ou=system" is based on the Distinguished Name of the admin. Normally, you will be provided by your administrator with a custom access, but for this tutorial we're relying on the default values to make things simple.

That's it. We've setup a simple Spring MVC 3 application, secured by Spring Security. Our users are authenticated against an LDAP provider. We've also explored how the various attributes map to an existing directory structure. This also means we can customize our mappings and assign different attribute names.

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-security-ldap/

You can download the project as a Maven build. Look for the spring-security-ldap.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security - MVC: Using an LDAP Authentication Provider ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

37 comments:

  1. hi, thank you about this article. can you demo to authenticate user data from mysql database by using hibernate.

    ReplyDelete
  2. @kanjon, this should be simple enough. If you look on the Spring 3 MVC - Hibernate 3: Using Annotations Integration Tutorial at http://krams915.blogspot.com/2010/12/spring-3-mvc-hibernate-3-using.html. All you need to do is edit the properties file and the hibernate language to MySQL. I'm gonna try making a demo for that. Thanks :)

    ReplyDelete
    Replies
    1. Thanks so much for your excellent doc. It's really helpful ...

      Cheers,
      HQ

      Delete
  3. Nice post but the download repo is empty

    ReplyDelete
  4. Hi, I ran the project via Maven on Tomcat, the log suggests it deployed correctly (no errors) but all I see is a 404 when I browse to http://localhost:8080/spring-security-ldap. What could I be doing wrong?

    ReplyDelete
  5. My apologies, I didn't realise I had to browse to http://localhost:8080/spring-security-ldap/krams/auth/login. Thanks for the tutorial.

    ReplyDelete
  6. Good Article. But most of the time, You want to authenticate to the LDAP with out manager-dn user/password. Here it assumes you have the manager-dn password. Could you please give an example which just authenticates the LDAP and also how to write our own implementation of assigning a role. something like overriding like and I can map my own role for a given user. This is more practical for most if us.

    Vam

    ReplyDelete
  7. Nice article. Could you please provide an example of how to authenticate a login user against Active Directory using LDAP protocol and assign the roles dynamically from database with out having to map the roles in XML configuration. Is it possible? Could you please guide me, I am new to Spring Security...

    ReplyDelete
  8. This is simply best and most detailed article man. I just need to authenticate instead of authorization can I remove group search filter and other stuff ?

    ReplyDelete
  9. One major point to note while authenticating against active directory is that it doesn't 't handle referral and you will get PartialResultException: Unprocessed Continuation Reference(s), to avoid this problem setIgnorePartialResultException(true), check Ldap authentication using spring security example for more details.Also I suggest using spring security framework for ldap authentication.

    ReplyDelete
  10. I am using net-beans 7.0.1 with glass-fish When i run the programme it provide an exception like below(I have copy and paste a part of that exception )

    If you are using LDAP with Spring Security, please ensure that you include the spring-ldap jar file in your application

    ReplyDelete
  11. Hi,
    Will you be able to post a tutorial about SSO with CAS and LDAP?

    Thanks

    ReplyDelete
  12. amazing tutorial ..... helped me allow users of certain roles to be authenticated to a url.

    ReplyDelete
  13. hi krams
    how can we authenticate a user in spring mvc.
    in a special application there is a sha512 password encoding +custom password encoding and that password is inserted to database.
    On user login the password has to convert to that old password encoding and validate with those in database.
    in applicationcontex-security.xml










    the CustomUserDetailsService class implements AuthenticationProvider its getting the password we typing in password field ,i converted this password with passwordencoding ,now i need to authenticate with database and logged in.so what things i need to do extra in the customclass to validate with custompassword.

    please help me
    thanks in advance

    ReplyDelete
  14. Hi krams,

    Thanks for amazing tutorial. LDAP can also store some user specific information. e.g. Phone Number. Can you please let me know how to retieve this information for logged in user.

    Thanks
    Shirish

    ReplyDelete
  15. Very very helpfull tutorial, TKS very much, but....if I want to get the roles from a database after login, what I need to set in the security:ldap-authentication-provider tag to it access my class, and what I need to return in the class? Have you an example?

    ReplyDelete
  16. Krams. You are awesome. That concludes this message.

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  18. what is the user name and password

    ReplyDelete
  19. great tutorial. Very straight forward. But I'm having an error when executing mvn jetty:run

    2012-08-16 21:54:08.963:/spring-security-ldap-embedded:INFO: Initializing Spring root WebApplicationContext
    [ERROR] [main 09:54:12] (DefaultAttributeTypeRegistry.java:lookup:192) attributeType w/ OID 2.5.4.16 not registered!
    [ERROR] [main 09:54:14] (ApacheDSContainer.java:start:180) Failed to create dc entry
    java.lang.IllegalArgumentException: [Assertion failed] - this expression must be true
    at org.springframework.util.Assert.isTrue(Assert.java:65)

    ReplyDelete
  20. Hi Krams,

    The example is really good. But I am facing a problem. In my example the authentication is happening successfully but authorization means the ROLE_ + String retreived from LDAP group is not working fine I quess. Thats why even though I am having correct users and groups it is always going to accessDenied page...

    ReplyDelete
    Replies
    1. i have the some problem.did you fixe it?

      Delete
  21. Ele ejemplo esta muy bueno pero al levantarlo en tomcat me arroja un error 404 al desplegar que haria para probar el proyecto a la perfeccion

    ReplyDelete
  22. thanks for ur tutorial ..., same as how we can apply the cache to the application same spring-ldap...
    its really help for me

    ReplyDelete
  23. excellent material for beginners..

    ReplyDelete
  24. The example is really good. But I am facing a problem. In my example the authentication is happening successfully but authorization means the ROLE_ + String retreived from LDAP group is not working fine I quess. Thats why even though I am having correct users and groups it is always going to accessDenied page...

    ReplyDelete
  25. Hi ,

    In the debug mode , i got this ,

    Got LDAP context on server ldap://testldap:389/dc=ab,dc=cd,dc=ef

    also
    searching forSearching for user 'xxxxx', with user search [ searchFilter: '(&(o
    ry=Person)(sAMAccountName={0}))', searchBase: 'DC=ab,DC=cd,DC=ef',scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]

    i am not able to authenticate still...

    what could be the error ?Please help..

    ReplyDelete
  26. Hi ,

    In the debug mode , i got this ,

    Got LDAP context on server ldap://testldap:389/dc=ab,dc=cd,dc=ef

    also
    searching forSearching for user 'xxxxx', with user search [ searchFilter: '(&(objectCategory=Person)(sAMAccountName={0}))', searchBase: 'DC=ab,DC=cd,DC=ef',scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]

    i am not able to authenticate stil...

    what could be the error ?Please help..

    ReplyDelete
  27. hi i m adarsh
    i m getting this exception
    [ERROR] [Scanner-2 09:36:38] (DefaultAttributeTypeRegistry.java:lookup:192) attributeType w/ OID 2.5.4.16 not registered!
    [ERROR] [Scanner-2 09:36:39] (ApacheDSContainer.java:start:182) Failed to create dc entry
    java.lang.IllegalArgumentException: [Assertion failed] - this expression must be true

    plz any one can let me know where i m wrong .

    ReplyDelete
  28. Hi, how can one reference an odjectClass in authentication manager?

    ReplyDelete
  29. Hi,
    Great article however I would like to know how in the ldap server I could give a specific user permissions and then use it in the Spring security. for example 'view_all_mails' permissions or 'delete_mail' permission

    ReplyDelete
  30. Hi,

    I deployed code in tomcat t.i am getting error. java.lang.Noclass found error. org/springframework/core/envEnvoirnmentCapble.

    I add spring-core.3.0.5 .i am getting error.Please help me resolve this issue.

    Regards,
    Venkat.

    ReplyDelete
  31. Good article! Congratulations guy!!

    ReplyDelete
  32. What is the username and password for logging into LDAP server successfully Login ?

    ReplyDelete
  33. Hi i am getting below error,

    attributeType w/ OID 2.5.4.16 not registered!

    Please help me to get away from this,

    Thanks,
    Kiran

    ReplyDelete