Category Archives: Java

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.

SaaS Application Design Discussion – Part IV

In the previous post, I discussed database design for saas application. To continue design discussion for our social pie saas application, in this post, we will discuss a few more ideas about how a user and user’s company will sign up for application. This will be a user story. We are building a SAAS application. To make it more viable, this application will use the freemium and pay model.

  1. In the freemium model – Any company can join and review what reports it will be able to see and what kind of marketing strategies it can design using those reports.
    1. 5 Reports
    2. Free Marketing Strategies
    3. Up to 3 users
    4. Limited usage of twitter and Instagram APIs
  2. In pay model – If a company opts to join a pay subscription, it will be able to get more advance reports, will be able to see reports in a different format, and can also get consultation about strategies for marketing.
    1. N number of reports – Your data, your freedom
    2. Marketing Consultation
    3. KPI tracker and notification
    4. Up to N users (won’t be implemented in first version)

User Flow

Once the user lands on the home page, he can opt for either model and sign up. An automated email will be sent to the user for a demo or sign up. Upon sign up, where the user will be entering details about himself and his company. This user will be an administrator and he can add other users with custom roles. The same user can go to reports tab and click on sync data. This will get the latest data from social media and update it in the database. Every new request will compare newly fetched data with current data in the database. If the new request has brought changes, it will be updated in the database. When generating reports, this data from the database will be cached.

We will not be fetching any on-the-fly data from Twitter and Instagram. Administrator users will have an option to send reports to other people from the company. There will be an email/download option.

There are some nitty-gritty details that I have not covered in this post. But with this post, we will be starting to develop a Saas application using java and spring-boot.

 

One Tip to Avoid Bouncy Castle Error

java.lang.NoSuchMethodError: org.bouncycastle.math.ec.ECCurve$Fp – Issue

In this post, I will discuss one tip everyone can use to avoid bouncy castle error.

Problem

Recently I was working on building a SOAP webservice where we were using Apache CXF libraries along with Spring boot. We built the webservice, but when we were sending a SOAP request through the client, we kept getting following error:

Caused by: java.lang.NoSuchMethodError: org.bouncycastle.math.ec.ECCurve$Fp.<init>(Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;)V
  at org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertCurve(Unknown Source)
  at org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertPoint(Unknown Source)
  at org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey.<init>(Unknown Source)
  at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePublic(Unknown Source)
  at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
  at sun.security.ssl.HandshakeMessage$ECDH_ServerKeyExchange.<init>(HandshakeMessage.java:1075)
  at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:284)
  at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
  at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
  at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
  at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:553)
  at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:412)
  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:179)
  at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:328)
  at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:612)
  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:447)
  at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:884)
  at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
  at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
  at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
  at org.springframework.ws.transport.http.HttpComponentsConnection.onSendAfterWrite(HttpComponentsConnection.java:121)

A Simple tip to avoid this error

We tried different things to resolve this issue. We tried to exclude bouncycastle jars from cxf-rt-ws-security dependencies we were using as we were pulling them from other dependencies. But this error would still pop up intermittently. Eventually, I figured out the issue. We had to add this dependency of bouncycastle explicitly as below in our Gradle build file. That’s when the error went away.

compile (‘org.bouncycastle:bcprov-jdk15on:1.56’) 

Conclusion

In this post, I showed how to use this one tip to avoid the error caused by the bouncy castle. If you enjoyed this post, subscribe to my blog here.

Design of REST API for web application

One reason I like to build an application in public is that it keeps me accountable. I can’t run away. If I don’t finish something, it’s ok. At least, I will have something done to show to people. Building in public is not a new idea, a lot of people have used it. In this post, I discuss the design of REST API for Social KPI.

In the previous post here, we discussed the architecture of the application we are building.  This will be an ongoing process as we continue to build our application and evolve.

We will follow the following tips to design REST APIs

  1. We will use Resource to represent object for REST APIs
  2. API endpoint will represent a resource object in the plural. Example – companies, users
  3. We will use HTTP status codes for success or failure of the request
  4. We will use JSON object to represent a response
  5. And we will use versioning to represent a version of APIs

As discussed in the previous post application idea, we will have APIs for companies, users of those companies, customers, clicks, engagements data. While concluding this short post, I want to say that the next post will include database design as well as URL design for REST APIs.

We will be using Spring Boot to build REST API.

In conclusion, I discussed the design of the REST API for the web application Social KPI. If you want to follow the progress, subscribe here.