A few weeks ago the spring greenhouse project was mentioned to me. This project shows how you can interact with services that use OAuth like Twitter, Facebook and Linkedin. Just a few days a go I noticed most of the code is now available through the spring-social project. Since we need this functionality for more and more projects I decided to create a very basic sample application to show you how it works.

If you want to use this for your project have a look at the greenhouse project of springsource. They have created some nice abstractions over multiple social websites. This blog is just to help you understand the mechanism behind it and the way it is implemented in the spring-social project.

What are we going to create?

We are going to create a sample with which you can authenticate against linkedin and print all your contacts and some data about your public profile. Linkedin uses OAuth and the sample will contain the OAuth authentication using the components as provided by the spring-social project.

Introduction to OAuth

So what is up with this OAuth. In just a few words, it is an authentication service. As an application you forward a visitor to the authentication service. The visitor authenticates itself and your application receives the result using a callback. If the result is positive, the visitor has authorized your application to act on the behalf of the visitor. That way you can use services of the provider without knowing who you are dealing with. It is also possible to store the provided authentication for future use. That is what the greenhouse application does, in this sample we ask for the authentication each new session.

There are some very good resources for learning about OAuth. So if you want to know what OAuth really is about and how it works I urge you to check the following links.

Linkedin API

Linkedin provides OAuth authentication. They have written a good manual about using linkedin OAuth for authentication and the way linkedin requires authorization to get to the users data. I especially like the image they have created to show how this process works

Let us have a look at the basic steps needed to get some data from linkedin. If they are not clear, check the code later on. I think you can follow along easily.

  • Request a api key and secret using your linkedin profile on this page: https://www.linkedin.com/secure/developer.
  • In your application, redirect user to the authentication page and provide your api key.
  • User authenticates himself on the linkedin website.
  • If not done before, user needs to authorize the application to act on behalf of him.
  • User gets redirected to your site with a request token and a verification code
  • Obtain an access token using the request token and the verification code.
  • Start interacting with linkedin using your api key and the obtained access token.

That is about it

Spring-social

What is this spring-social. It is a new project that recently published M1. It provides support to interact with multiple social websites through a consitent api. There are integrations for Linkedin, Twitter, FaceBook and TripIt. There is a blog post from Craig Walls, one of the creators, that gives more details.

Show me the code

Finally, let us have a look at the code. You can find the code through github. It is a very basic spring mvc application. The most interesting part is within the class nl.gridshore.samples.springoauth.web.ConnectController.In the next code blocks I show you the methods that handle all the different stages of getting data from linkedin. Let us start by checking if the user is already connected to linked in or not.

@RequestMapping(value = "linkedin", method = RequestMethod.GET)
public String showConnectLinkedin(WebRequest request) {
    Token accessToken = obtainAccessTokenFromSession(request);
    if (accessToken == null) {
        return "connect/linkedin_connect";
    } else {
        return "connect/linkedin_connected";
    }
}
private Token obtainAccessTokenFromSession(WebRequest request) {
    return (Token) request.getAttribute(OAUTH_ACCESS_TOKEN_ATTRIBUTE, WebRequest.SCOPE_SESSION);
}

If you are authenticated with linkedin, the access token is stored in the session. Therefore we check for availability of this token in the session to determine if we need to show the page with the redirect to linkedin or the page with the options you have to ask linkedin for information. For now we assume that the user is not authenticated yet and he pushes the button to authenticate with linkedin. The form post is received by the following method.

@RequestMapping(value = "linkedin", method = RequestMethod.POST)
public String requestConnectionLinkedin(WebRequest request) {
    Token requestToken = getOAuthService().getRequestToken();
    request.setAttribute(OAUTH_REQUEST_TOKEN_ATTRIBUTE, requestToken, WebRequest.SCOPE_SESSION);
    return "redirect:" + "https://www.linkedin.com/uas/oauth/authorize?oauth_token=" + requestToken.getToken();
}

private OAuthService getOAuthService() {
    OAuthConfig config = new OAuthConfig();
    config.setRequestTokenEndpoint("https://api.linkedin.com/uas/oauth/requestToken");
    config.setAccessTokenEndpoint("https://api.linkedin.com/uas/oauth/accessToken");
    config.setAccessTokenVerb(Verb.POST);
    config.setRequestTokenVerb(Verb.POST);
    config.setApiKey(apiKey);
    config.setApiSecret(apiSecret);
    config.setCallback(callbackUrl);

    return new OAuth10aServiceImpl(
            new HMACSha1SignatureService(),
            new TimestampServiceImpl(),
            new BaseStringExtractorImpl(),
            new HeaderExtractorImpl(),
            new TokenExtractorImpl(),
            new TokenExtractorImpl(),
            config);
}

The code shows we need to create an OAuthCOnfig object using the applications api key and secret and the callback url. Using this service you can generate a request token. This token is provided to linkedin using the redirect service. Now the user does his thing in linkedin and he should see a screen like this:

Screen shot 2010-11-04 at 10.29.11.png

If the user pushes the “ok, I’ll allow it button”, we get the request token back together with a verification number to the url as provided by the callback url. The following code shows the receiving method.

    @RequestMapping(value = "linkedin", method = RequestMethod.GET, params = "oauth_token")
    public String authorizeCallback(@RequestParam(value = "oauth_verifier", defaultValue = "verifier") String verifier,
                                    WebRequest request) {
        Token requestToken = obtainRequestTokenFromSession(request);
        Token accessToken = getOAuthService().getAccessToken(requestToken, new Verifier(verifier));
        request.setAttribute(OAUTH_ACCESS_TOKEN_ATTRIBUTE, accessToken, WebRequest.SCOPE_SESSION);
        return "redirect:linkedin";

    }

As you can see we obtain the request token from the session. Using this request token and the received verification code we obtain the access token. This access token is then used for all calls to linkedin. That is shown in the following code block to obtain all connections of the authenticated user.

@RequestMapping(value = "linkedin/connections", method = RequestMethod.GET)
public String connections(WebRequest request) {
    LinkedInTemplate template = createLinkedInTemplate(request);
    List<LinkedInProfile> connections = template.getConnections();
    request.setAttribute("connections", connections, WebRequest.SCOPE_REQUEST);
    return "connections";
}

Summary

Pretty amazing that it takes only this amount of lines of code to communicate with a service like linkedin. I like it. I personally like the abstraction as used within the greenhouse application from springsource better than doing this stuff yourself. Still it does give you some insights into the way social integration works.

Connecting to Linkedin using spring-social
Tagged on: