Securing REST Web Services against LDAP

motif

Many Mule users create RESTful services but they are not always clear on the way to authenticate and apply authorization to a RESTful Web Service. I have seen questions about this topic so I decided to write a tutorial that covers a common use case. We’re going to use Jersey, Spring and LDAP and of course Mule to pull  it all together.  I will show you how to do the following:

  1. Expose REST resource using Jersey
  2. Secure the REST resource using HTTP Basic Authentication
  3. Authenticate and authorize users against an LDAP Directory
  4. Apply authorisation based on users groups to this REST resource

1. Exposing REST resource using Jersey

Jersey is a JAX-RS (JSR-311) implementation. JAX-RS is a specification that provides a series of annotations and classes, which make it possible to build RESTful services. The Mule Jersey module makes it possible to deploy these annotated classes inside .

The example we discussed has exposed a HelloWorldService, and this is how our component will look:

The Mule endpoint to expose the service above, is as following:


<inbound-endpoint address="http://localhost:65069/jersey"/>      
<jersey:resources>          
<component class="org.mule.transport.jersey.HelloWorldResource"/>      
</jersey:resources>

2. Securing HelloWorldResource using Http Basic Authentication

We will use Spring Security 3.0 as a security manager inside Mule,  below is the configuration to define Spring Security

You can see  that to make the endpoint secure I have added the HTTP-Security filter. It will force HTTP Basic Authentication on your HTTP resource. For more information about Spring Security check out Configure Spring Security Manager and if you are not familiar with  HTTP Basic authentication you can find out more here: Basic_access_authentication.

3. LDAP configuration

For users coming from Mule 2.2.x, please note that Spring Security 3.x LDAP API has been changed a lot, so take a close look at all the API difference attached with this example.

Since this example is not about teaching and setting up the LDAP configuration I won’t go into details about it. Please follow this document link to get more details on Mule LDAP configuration.

4. Apply authorisation based on users groups to this REST resource

Finally,  we want to make sure that only an Authorized and Authenticated user should be able to access our resource. For Authentication we will use Spring’s security LDAP authentication ProviderManager like following:

For Authorization we will use an interceptor that intercepts the incoming request and authenticate based on the user. Now lets say, you want to only authorize  users who have a ROLE = PROGRAMME to access your resource. Spring Security provides you to do so using MethodSecurityInterceptor and following is the snippet:

<bean class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor"
          id="myComponentSecurity">
        <property name="authenticationManager" ref="authenticationManager"/>
        <property name="accessDecisionManager" ref="accessDecisionManager"/>
        <property name="securityMetadataSource"
                  value="org.mule.transport.jersey.HelloWorldResource.sayHelloWithUri=ROLE_PROGRAMMERS">
           
        </property>
</bean>

The above configuration explains that only user with ROLE = PROGRAMMER should be able to authorize to access this request. You can find the complete configuration for this in the spring-security.xml file inside the example Mule App.

Lets Try It

To run the example As-It-Is, you require a LDAP server, I recommend to use apache DS as the example is fully tested on this (you can download apache ldap from here: http://directory.apache.org/).

You need to install apache DS and the studio for GUI based interaction with your ldap server. Once installed, I have added a sample ldif file with this example, jerseyLdap.ldif.

You can import this ldif using apache D Studio:
http://directory.apache.org/studio/static/users_guide/ldap_browser/tools_ldifimport_wizard.html

Once you have pache DS is up and running, have imported the file and have the spring-security.xml in the example is pointing to your ldap you are ready to run the app.

The example attached is a maven project, which has 3 test case methods:
1. testGoodAuthenticationBadAuthorisation
2. testGoodAuthenticationGoodAuthorisation
3. testBadAuthenticationBadAuthorisation

The names should be self explanatory.

To test run “mvn test”

If you run the example as mule app, then try hitting this in browser:
http://localhost:65069/helloworld/test

The browser should prompt you with username and password. The user name and password to use: kmoe/test (if you are using jerseyLdap.ldif, this user has ROLE = PROGRAMMER). Any other user (jdoe/123, etc) should not be allowed to access the resource.

Downloads

Source Download:  LDAP JERSEY EXAMPLE
Mule App Only: mule-jerseyLdap.zip


We'd love to hear your opinion on this post


2 Responses to “Securing REST Web Services against LDAP”

  1. Hi Jaskirat,
    I tried this, but getting this exception..
    I have setup the ldap properly..

    Exception stack is:
    1. Cannot convert value of type [java.lang.String] to required type [org.springframework.security.access.method.MethodSecurityMetadataSource] for property ‘securityMetadataSource’: no matching editors or conversion strategy found (java.lang.IllegalStateException)
    org.springframework.beans.TypeConverterDelegate:231 (null)

    Requesting help on this..

  2. The problem is solved.

    I was using spring-security 3.1.0.RC3 which actually has a bug reported.
    http://forum.springsource.org/archive/index.php/t-116559.html?s=2593f3104cd96526128439b31ac16a0b

    So I changed the version of spring-security to 3.0.7 Release.
    Now the application is working fine.

    Thanks.