Integrating your Java Spring MVC webapp with Facebook – Doing the OAuth Dance

Integrating your Java Spring MVC webapp with Facebook – Doing the OAuth Dance

In this multi-part post, I’ll show you how to integrate your spring mvc web application with Facebook and do all sorts of interesting things like accessing your data, your friend’s data, posting to walls among other interesting things. In this this post however, we will focus on a pre-requisite, which is allowing people to login into your application using their facebook accounts and asking them for various permissions while doing it.

Integration with Facebook can happen either at the client-side, where integration typically would happen via javascript directly from the page or it can happen at the server-side where server-side php/java/ruby code performs the integration. Since, we will be discussing in context of Java, Spring and Spring MVC, ours will be a server side implementation.

Registering a new application in Facebook

The first step of course is registering your application with Facebook. All you need is an account on facebook. You can register you application by going to the following URL https://developers.facebook.com/apps

Registering an application on facebook
Registering an application on facebook

 

While there are lots of configurations you can make while setting up a Facebook application (things like setting up your logos, configuring an administrator email address etc) we will stick to configuring the most important one: the call back URL. In order to understand why this is important, we need to understand a typical OAuth flow which we will do in a bit.

Setting up your facebook application
Setting up your facebook application

Understanding the typical OAuth flow. Case in point: Facebook

Accessing any API that is OAuth compliant typically follows the same 3 step process. This process is commonly referred to as the OAuth dance. The pre-requisite to the OAuth dance is registering the application/API consumer as we have already discussed above in context of facebook. The steps of the OAuth dance are:

  1. Use the application id and client secret to generate a authorization code
  2. Use the authorization code to generate an access token
  3. Use the access token to access the API

The terms application id, client secret, authorization code and access token are used by Facebook and maybe different for different implementers but the overall idea and flow would be similar if not exactly the same.

The code

I am going to paste the code here and then walk you through the OAuth dance. Be aware though. This is not production quality code. It is just to give you an idea of how things works. Tweak it according to your needs.


@RequestMapping(value = "/social/facebook")
@Controller
public class FacebookController {

	private static final String SCOPE = "email,offline_access,user_about_me,user_birthday,read_friendlists";
	private static final String REDIRECT_URI = "http://localhost:8080/platform-services/social/facebook/callback";
	private static final String CLIENT_ID = "Your Client Id";
	private static final String APP_SECRET = "Your App Secret";
	private static final String DIALOG_OAUTH = "https://www.facebook.com/dialog/oauth";
	private static final String ACCESS_TOKEN = "https://graph.facebook.com/oauth/access_token";

	@RequestMapping(value = "/signin", method = RequestMethod.GET)
	public void signin(HttpServletRequest request, HttpServletResponse response)
               throws Exception {
		try {
			//TODO: if already have a valid access token, no need to redirect, just login
			response.sendRedirect(DIALOG_OAUTH+"?
                              client_id="+CLIENT_ID+
                              "&redirect_uri="+REDIRECT_URI+
                              "&scope="+SCOPE);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@RequestMapping(value = "/callback", params = "code", method = RequestMethod.GET)
	@ResponseBody
	public void accessCode(@RequestParam("code") String code,
                                HttpServletRequest request,
                                HttpServletResponse response) throws Exception {
		try {
			response.setContentType("text/html");
			String responseString = IntegrationBase.readURLGET(ACCESS_TOKEN,
                            new String []{"client_id","redirect_uri","code", "client_secret"},
                            new String[]{CLIENT_ID,REDIRECT_URI,code,APP_SECRET});
			response.getWriter().write(responseString);
			response.flushBuffer();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@RequestMapping(value = "/callback", params = "error_reason", method = RequestMethod.GET)
	@ResponseBody
	public void error(@RequestParam("error_reason") String errorReason,
                           @RequestParam("error") String error,
                           @RequestParam("error_description") String description,
                           HttpServletRequest request, HttpServletResponse response) throws Exception {
		try {
			response.sendError(HttpServletResponse.SC_UNAUTHORIZED, description);
			System.out.println(errorReason);
			System.out.println(error);
			System.out.println(description);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

Use the application id and client secret to generate a authorization code

According to the code above, you can see that we have the following service endpoints

  1. /social/facebook/signin
  2. /social/facebook/callback?code=x (where user gives permissions)
  3. /social/facebook/callback?error_reason=x&error=y&error_description=z (where user does not give permissions)
The service client calls /social/facebook/signin service. The call is received in the controller from lines 13-34. We simply redirect the HTTP call to
Let’s breakdown this URL:
https://www.facebook.com/dialog/oauth – This is the URL to which our application would redirect to. This will show the facebook login page for our users.
The URL takes in 3 query string parameters.
  • client_id: This is the ‘App Id’ we got when we created our app in facebook (refer to the second image in this post)
  • redirect_uri: Facebook calls this URL once user has successfully logged in and accepted or rejected permissions. The URL must be the same as mentioned in the ‘Site URL ‘ field while creating the app (again refer to the second image). If your redirect URL needs to have query string parameters, you don’t have to specify those in the ‘Site URL’ field as it only requires the base URL to be the same.
  • scope: Using the scope parameter, you specify the list of permissions you require from the user. For example: ‘user_birthday’ which give us access to the users birth date he has entered in facebook. A list of permissions is available at https://developers.facebook.com/docs/reference/api/permissions/
Redirecting to the complete URL takes you to the facebook login page in case you are not logged in. After entering your facebook username and password, you get presented with the following pages asking you add your application and provide/reject requested permissions.
Clicking the ‘Go to App’ button opens up the following screen.

When you click on either Allow or Skip, facebook is going to make a HTTP call on the redirect_uri that we sent in as part of our redirect to the facebook oauth dialog.

If you allow the application the permissions it requires, facebook calls the redirect uri with an additional code parameter. In our controller, this corresponds to the function at Line 28 being called. Otherwise, the function at Line 46 is called with error, error_reason, and error_description parameters.

The code is the authorization code that is an intermediate code required to get the access token. From lines 33-37, we make an HTTP call (using our own class IntegrationBase) to the URL https://graph.facebook.com/oauth/access_token?client_id=<your-client-id>&redirect_uri=<the-url-facebook-will-redirect-to>&code=<the-authorization-code-we-received-earlier>&client_secret=<the-client-secret>

the redirect_uri must be the same as in the earlier call to facebook.

As a result of this call, if all is well and your code, along with other parameters are valid, you will get the a response similar to this:

access_token=<accesstoken>&expires=<number-of-seconds-till-this-token-expires>

This access token can now be used to access facebook data you required access to and asked permission for in the scope query string parameter sent earlier to facebook while asking for the authorization code.

In a later post, we will see how to post on a wall and get access to friend information among other actions using our access token.

More information about the Oauth dance can be found on the facebook developer site at http://developers.facebook.com/docs/authentication/

  • tropical

    Very clear. Thanks for explanation. Just one question – what does the integrationbase class do exactly?

    • prasad

      hi did you get answer to your question?

  • teja

    is any jar files required

  • Dharmi

    but I wonder why I see this error from facebook redirect, when I pass the localhost url as siteURL “Given URL is not allowed by the Application configuration.: One or more of the given URLs is not allowed by the App’s settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App’s domains.”

    • syntx

      localhost will not work. You need a public URL that you first have to register with your facebook app for this redirection to will.

      • Dharmi

        Thanks Syntx.

        after some wrestling ‘localhost’ did work. I was trying to tweak spring-social-quickstart sample from springsource to accommodate into my app. One nice feature FB appears to be doing is, its validating the ‘redirect_uri’, if it isn’t, it throws the generic error message I mentioned. My mistake was, the context path after my localhost URI was missing. I placed it, and it started working.

  • prasad

    Hi

    Will you please provide the definition of IntegrationBase.readURLGET method

    Thanks

  • Shuchivrat

    Hi, I tried to integrate the facebook controller in my spring MVC application. but, it cannot find IntegrationBase class….anyone can please help ??

    • admin

      IntegrationBase class simply creates a HTTP request. You can use any API/library/function for this purpose.