Go to content

Retrieve Facebook profile data in Java: Spring Social

Published on

In the previous blogpost I explained how you can get Facebook profile data using Scribe. This blogpost will do the same for Spring Social.

Setup

The Maven dependency for Spring Social Facebook:

<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-facebook</artifactId>
<version>1.0.3.RELEASE</version>
</dependency>

Setup of the Spring controller:

@Controller
public class FacebookSpringSocialAuthenticator {
public static final String STATE = "state";
private String applicationHost;
private FacebookConnectionFactory facebookConnectionFactory;

@Autowired
public FacebookSpringSocialAuthenticator(
@Value("#{properties['facebook.clientId']}")
String clientId,
@Value("#{properties['facebook.clientSecret']}")
String clientSecret,
@Value("#{properties['application.host']}")
String applicationHost) {
this.applicationHost = applicationHost;
facebookConnectionFactory =
new FacebookConnectionFactory(clientId, clientSecret);
}
}

Start the authentication

@RequestMapping("/auth/facebook")
public RedirectView startAuthentication(HttpSession session)
throws OAuthSystemException {
String state = UUID.randomUUID().toString();
session.setAttribute(STATE, state);

OAuth2Operations oauthOperations =
facebookConnectionFactory.getOAuthOperations();
OAuth2Parameters params = new OAuth2Parameters();
params.setRedirectUri(applicationHost + "/auth/facebook/callback");
params.setState(state);

String authorizeUrl = oauthOperations.buildAuthorizeUrl(
GrantType.AUTHORIZATION_CODE, params);
return new RedirectView(authorizeUrl);
}

Handle the callback

@RequestMapping("/auth/facebook/callback")
public RedirectView callBack(@RequestParam("code") String code,
@RequestParam("state") String state,
HttpSession session) {
String stateFromSession = (String) session.getAttribute(STATE);
session.removeAttribute(STATE);
if (!state.equals(stateFromSession)) {
return new RedirectView("/login");
}

AccessGrant accessGrant = getAccessGrant(code);

String facebookUserId = getFacebookUserId(accessGrant);
session.setAttribute("facebookUserId", facebookUserId);
return new RedirectView("/logged-in");
}

Retrieve the AccessGrant

private AccessGrant getAccessGrant(String authorizationCode) {
OAuth2Operations oauthOperations =
facebookConnectionFactory.getOAuthOperations();
return oauthOperations.exchangeForAccess(authorizationCode,
applicationHost + "/auth/facebook/callback", null);
}

Get the Facebook user id

Spring social splits up the profile response into several classes. With Connection#fetchUserProfile you get the username, but not the user’s identifier, which is retrieved with Connection#getKey.

private String getFacebookUserId(AccessGrant accessGrant) {
Connection<Facebook> connection =
facebookConnectionFactory.createConnection(accessGrant);
ConnectionKey connectionKey = connection.getKey();
return connectionKey.getProviderUserId();
}

Conclusion

Spring Social has built in methods to convert the JSON response of the profile into Java objects which Scribe doesn’t do for you. Its setup is a bit simpler and there are no traces of OAuth 1 support in the Facebook classes. Spring social seems to handle the flow a bit slower (200-300 ms slower) than Scribe.