Monthly Archives: May 2018

LDAP Authentication with Spring Boot LDAP

In this article, I will show how to achieve LDAP authentication using spring boot plugin for LDAP.

What you will need

  • Java 8
  • IntelliJ
  • Apache Directory Server
  • Apache Directory Studio
  • Spring Boot

Implementation

To use LDAP for authentication with Spring Boot, definitely set up a LDAP server and we will use Apache Directory Server in our case. I will not be showing “How to set up and add LDIF entries” as this is entirely different topic. But I have two users John Doe and James Hook in my LDAP repository. I will use those accounts to login.

Set up Spring Boot with LDAP dependencies

As part of implementing this, we will add following gradle dependencies:

compile('org.springframework.boot:spring-boot-starter')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.ldap:spring-ldap-core')
compile('org.springframework.security:spring-security-ldap')
compile('org.springframework:spring-tx')
compile('org.apache.directory.server:apacheds-server-jndi:1.5.5')

For our task, spring-ldap-core and spring-security-ldap are important dependencies.

Rest Controller

We will create a simple rest controller that will display our sample page. This sample page will be secured and to access it, an user will have to authenticate.

package com.betterjavacode.SpringBootLdapApplication.Controllers;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController
{
    @GetMapping("/")
    public String index()
    {
        return "Welcome to Spring Boot Ldap Application Page";
    }
}

Security Configuration

We will add our security configuration by adding a WebSecurityConfig class that extends WebSecurityConfigurerAdapter.

package com.betterjavacode.SpringBootLdapApplication;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.httpBasic().and().authorizeRequests().anyRequest().authenticated().and().formLogin().and().csrf().disable();
    }

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception
    {
        authenticationManagerBuilder
                .ldapAuthentication()
                .contextSource().url("ldap://localhost:10389/o=betterjavacode")
                .managerDn("uid=admin,ou=system").managerPassword("secret")
                .and()
                .userSearchBase("ou=people")
                .userSearchFilter("(uid={0})");
    }

}

Now if we look at this, when a user will launch the application, he will be challenged with a login form based on formLogin() . Once the user enters credentials, he will be redirected to home page.

The result for that will look like below:

LDAP Authentication

Once the user enters credentials:

LDAP Authentication - Login Successful

Conclusion

In this post, we showed how to use LDAP for authentication using Spring boot.

References

  1. Spring Boot LDAP – Spring Boot LDAP
  2. Authentication using LDAP – LDAP Authentication

 

Custom Twitter Client vs Spring Boot Twitter Plugin

To use twitter data in my saas application, I was going to write my own custom Twitter client by doing a rest call. However, I found out Spring Boot offers a Twitter plugin that can be used to fetch Twitter data. Neat.

In this post, I will show some comparison of these two approaches and why one can choose over another:

Custom Twitter Client

So custom twitter client will be a standalone client which will build an HTTP entity with client secrets that are needed to authenticate with Twitter API. In this client, we will use restOperations to call API endpoint passing HTTP entity and the REST call will respond with Twitter Data Model.

This will look like below:

public TwitterDataModel getTwitterData(long accountId)
{
    String url = buildRestUrl(accountId);
    ParameterizedTypeReference<HashMap<Long, TwitterDataModel>> responseType = new ParameterizedTypeReference<HashMap<Long, TwitterDataModel>>(){};
    HttpEntity entity = buildHttpEntity(CLIENT_ID, CLIENT_SECRET);
    Map<Long, TwitterDataModel> twitterDataModelMap = restOperations.exchange(url, HttpMethod.GET, entity, responseType).getBody();

    Long keyForData = new Long(accountId);
    TwitterDataModel twitterDataModel = twitterDataModelMap.get(keyForData);

    return twitterDataModel;
}

public String buildRestUrl(long accountId)
{
    return TWITTER_REST_ENDPOINT + accountId + TWITTER_REST_API;
}

There is nothing much wrong with this approach, except the fact that we will have to write an extra TwitterDataModel business object. Also, this business model should be created before we do the actual REST call.

Spring Boot Twitter Plugin

To use this plugin, first, we need to add the plugin in Gradle or maven like below:

compile('org.springframework.social:spring-social-twitter')

Once we have this plugin, we can add an object of type Twitter in our code to call REST APIs.

This will look like below:

private final Twitter twitter;

public TwitterDataModel getTwitterData(long accountId)
    {
        String url = buildRestUrl(accountId);
        ParameterizedTypeReference<HashMap<Long, TwitterDataModel>> responseType = new ParameterizedTypeReference<HashMap<Long, TwitterDataModel>>(){};
        HttpEntity entity = buildHttpEntity(CLIENT_ID,CLIENT_SECRET);

        Map<Long, TwitterDataModel> twitterDataModelMap = twitter.restOperations().exchange(url, HttpMethod.GET, entity, responseType).getBody();

        Long keyForData = new Long(accountId);
        TwitterDataModel twitterDataModel = twitterDataModelMap.get(keyForData);

        return twitterDataModel;
    }

    public String buildRestUrl(long accountId)
    {
        return TWITTER_REST_ENDPOINT + accountId + TWITTER_REST_API;
    }

The major advantage of this plugin is that we can get the data in Twitter Data Model that twitter offers. An then we can go on to use to handle our data.

Conclusion

In this post, I showed how we can use a Spring Boot Twitter social plugin to gather Twitter data.