Retrieve Facebook profile data in Java: Spring Social
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.