OAuth 2.0 based Facebook authentication. Spring framework Java authentication client

This tutorial will cover how to obtain user data from the facebook secure server and use that to authenticate a user based on the credentials obtained.

Image

First Step is to prepare a Facebook App that will allow for this authentication:

1. Go to Apps and Create a new app
2. Add the display name and namespace
3. Obtain the APP_ID and SECRET_KEY for this app
4. Setup the website that will authenticate through this app
Go to settings and select Add Platform in the Basic settings configuration add website URL(localhost:8080) for your test.

The facebook app is ready for integration with your web service. I have a spring service which is called by a controller call which is described below:

 

/**
* @author Rahul Vishwakarma
*
* This service allows the authentication with the facebook authorization and authentication server
* An access token is obtained from the facebook server which is used to access the users data
*
*/
@Service
public class OAuthFacebookService {
/** Logger for this class and subclasses */
private static final Logger log = LoggerFactory.getLogger(OAuthSocialService.class);
@Autowired
private ConfigurationManager configurationManager;

/**TODO: Move all these to configuration and access through COnfiguration Manager**/
private static final String[] SCOPE = new String[] {"publish_stream",
"email",
"user_about_me",
"offline_access",
"user_birthday",
"read_friendlists"};

private static final String REDIRECT_URI = "http://localhost:8080/GenesisService/register/social/facebook/callback";
private static final String CLIENT_ID = "1428804717404113";
private static final String APP_SECRET = "b979e221dd8a778df420644c77c9ea00";
private static final String DIALOG_OAUTH = "https://graph.facebook.com/oauth/authorize";
private static final String ACCESS_TOKEN = "https://graph.facebook.com/oauth/access_token";

public String getLoginRedirectURL(String type) {
String url = DIALOG_OAUTH+"?client_id=" +
CLIENT_ID + "&display=page&redirect_uri=" +
REDIRECT_URI+"&scope="+StringUtils.arrayToCommaDelimitedString(SCOPE);
log.info("URL:"+url);
return url;
}
public String getAuthURL(String authCode) {
String url = ACCESS_TOKEN+"?client_id=" +
CLIENT_ID+"&redirect_uri=" +
REDIRECT_URI+"&client_secret="+APP_SECRET+"&code="+authCode;
log.info("URL:"+url);
return url;
}

public String getFacebookAccessToken(String code){
String token = null;
if (code != null && ! "".equals(code)) {
String newUrl = getAuthURL(code);
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
HttpGet httpget = new HttpGet(newUrl);
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httpget, responseHandler);
log.info("ResponseBody: "+responseBody);
token = org.apache.commons.lang.StringUtils.removeEnd
(org.apache.commons.lang.StringUtils.removeStart(responseBody, "access_token=") ,"&expires=5180795");
log.info("Token: "+token);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpclient.getConnectionManager().shutdown();
}
}
return token;
}

public String getUserData(String accessToken) {
String email = null;
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
if (accessToken != null && ! "".equals(accessToken)) {
String newUrl = "https://graph.facebook.com/me?access_token=" + accessToken;
httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(newUrl);
System.out.println("Get info from face --> executing request: "
+ httpget.getURI());
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httpget, responseHandler);
log.info("Obtained response from FB: "+responseBody);
ObjectMapper mapper = new ObjectMapper();
FBUserSocialData fb = mapper.readValue(responseBody, FBUserSocialData.class);
log.info("Facebook Data: "+fb.toString());
/**
* Do anythign with this user data
* 1. Create the user details data and register this user
* 2. Create a session for this user and allow for authenticated login to the system
*/

} else {
System.err.println("Token for facebook is null");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
httpclient.getConnectionManager().shutdown();
}
return email;
}
}

This service will be accessed by two sets of REST controller calls.

/facebook/signin  –  call will connect with Facebook and ask you to enter the credentials for authentication. A successful authentication generates a code contained in the URL

/facebook/callback – This service will take the code and obtain and access token. This access token is used to retrieve the final user data.

@RequestMapping(value = "/register/social/facebook/signin", method = RequestMethod.GET)
public void signin(HttpServletRequest request, HttpServletResponse response)
throws Exception {
try {
response.sendRedirect(oAuthSocialService.getLoginRedirectURL(""));
} catch (Exception e) {
e.printStackTrace();
}
}
@RequestMapping(value = "/register/social/facebook/callback", params = "code", method = RequestMethod.GET)
@ResponseBody
public void accessCode(@RequestParam("code") String code, HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
//Obtain an access token
String accessToken = oAuthSocialService.getAccessToken(code);
//Access the user data based on this token
oAuthSocialService.getUserData(accessToken);
} catch (Exception e) {
e.printStackTrace();
}
}

 

This is all you need to setup a basic authentication with the Facebook server. In order to use this in live environment we will have to make the facebook app public after submitting for review by facebook.

A sample response data procured by using this authentication is as below:

22-Jun-2014 02:30:00,435-INFO - OAuthSocialService:110 - 
Facebook Data: FBUserSocialData [id=268491463338606, birthday=66/66/6666, email=rahul_32346@dohoo.com, first_name=Rahul, gender=male,last_name=Vishwakarma,
link=https://www.facebook.com/app_scoped_user_id/268491463338606/, locale=en_US,
name=Rahul Vishwakarma, timezone=5.5, updated_time=2014-06-21T08:39:39+0000, verified=true]