Spring MVC + Security 3.0.5.RELEASE
Apache Oltu 1.0.1-SNAPSHOT
POM:
<!-- add spring / security / mvc dependencies -->
<!--DO NOT USE version 1.0.0 which causes oauth2 phrase2 auth problem with Google -->
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.common</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
Step 1: send request to get authorization code
Apache Oltu has defined some oauth providers, e.g. google, facebook, then you need to do something like:OAuthClientRequest request = OAuthClientRequest
.authorizationProvider(OAuthProviderType.GOOGLE)
.setClientId(YOUR_CLIENT_ID)
.setRedirectURI(YOUR_REDIRECT_URI)
.setResponseType("code")
.setScope("https://www.googleapis.com/auth/userinfo.email")
.buildQueryMessage();
response.sendRedirect(request.getLocationUri());
If the oauth provider is not defined in Oltu, then set authorization location manually:
OAuthClientRequest request = OAuthClientRequest
.authorizationLocation("https://api.login.yahoo.com/oauth2/request_auth")
.setClientId(YOUR_CLIENT_ID)
.setRedirectURI(YOUR_REDIRECT_URI)
.setResponseType("code")
.buildQueryMessage();
response.sendRedirect(request.getLocationUri());
For oauth providers not lised in Oltu, here are some URLs
YAHOO_AUTHORIZATION_URL = "https://api.login.yahoo.com/oauth2/request_auth";
YAHOO_TOKEN_URL = "https://api.login.yahoo.com/oauth2/get_token";
YAHOO_GUID_URL = "http://social.yahooapis.com/v1/me/guid";
YAHOO_USER_PROFILE_URL = "https://social.yahooapis.com/v1/user/__USERID__/profile?format=json";
TWITTER_REQUEST_TOKEN_URL = "https://api.twitter.com/oauth/request_token";
TWITTER_AUTHORIZATION_URL = "https://api.twitter.com/oauth/authorize";
TWITTER_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
TWITTER_PROFILE_URL = "https://api.twitter.com/1.1/users/profile_banner.json"
Step 2: get access code
Do the following in your code linking to REDIRECT_URI2.1 Get authorization code:
OAuthAuthzResponse oar = OAuthAuthzResponse.oauthCodeAuthzResponse(httpRequest);
String code = oar.getCode();
2.2 Use Oltu to get access token, e.g. from Google
OAuthClientRequest oauthRequest = OAuthClientRequest
.tokenProvider(OAuthProviderType.GOOGLE)
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setRedirectURI(REDIRECT_URI)
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setCode(code)
.buildBodyMessage();
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
final OAuthAccessTokenResponse oAuthResponse = oAuthClient.accessToken(oauthRequest, "POST");
String accessToken = oAuthResponse.getAccessToken();
long expiresIn = oAuthResponse.getExpiresIn();
Same code to get access token from FACEBOOK
2.3 Use Apache Httpclient to get access token from Yahoo
I cannot get Oltu working with Yahoo due to the data being sent from Oltu (HTTP header) is not accepted by YahooHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(OAuth2Manager.YAHOO_TOKEN_URL);
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("client_id", CLIENT_ID);
params.add(new BasicNameValuePair("client_secret", CLIENT_SECRET);
params.add(new BasicNameValuePair("redirect_uri", REDIRECT_URI);
params.add(new BasicNameValuePair("code", code));
params.add(new BasicNameValuePair("grant_type", "authorization_code"));
params.add(new BasicNameValuePair("response_type", "code"));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
String encodedValue=new String(Base64.encodeBase64(CLIENT_ID+":"+CLIENT_SECRET).getBytes("UTF-8"));
httppost.setHeader("Authorization", "Basic "+encodedValue);
HttpResponse oresponse = httpclient.execute(httppost);
org.apache.http.HttpEntity entity = oresponse.getEntity();
String theString = IOUtils.toString(entity.getContent(), "UTF-8");
// parse JSON string here ...
final JSONObject obj = new JSONObject(theString);
String access_token = obj.getString("access_token");
String xoauth_yahoo_guid = obj.getString("xoauth_yahoo_guid");
Step 3: retrieve user information
3.1 Google
OAuthClientRequest bearerClientRequest = new OAuthBearerClientRequest("https://www.googleapis.com/plus/v1/people/me").setAccessToken(accessToken).buildQueryMessage();
OAuthResourceResponse resourceResponse = oAuthClient.resource(bearerClientRequest, "GET", OAuthResourceResponse.class);
String userinfoJSON = resourceResponse.getBody();
final JSONObject obj = new JSONObject(userinfoJSON);
final JSONArray emails = obj.getJSONArray("emails");
final int n = emails.length();
for (int i = 0; i < n; ++i) {
final JSONObject email = emails.getJSONObject(i);
String type = email.getString("type");
if("account".equals(type)) {
System.out.println(email.getString("value"));
}
}
String googleid = obj.getString("id");
String fname = obj.getJSONObject("name").getString("givenName");
String lname = obj.getJSONObject("name").getString("familyName");
3.2 Facebook
A bit different from 3.1,// Facebook’s response is not fully compliant with the final version of the OAuth 2 specification, but it can be parsed using the class GitHubTokenResponse.
GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(oauthRequest, GitHubTokenResponse.class);
String accessToken = oAuthResponse.getAccessToken();
OAuthClientRequest bearerClientRequest = new OAuthBearerClientRequest("https://graph.facebook.com/me?fields=id,first_name,last_name,email")
.setAccessToken(accessToken).buildQueryMessage();
OAuthResourceResponse resourceResponse = oAuthClient.resource(bearerClientRequest, "GET", OAuthResourceResponse.class);
String userinfoJSON = resourceResponse.getBody();
final JSONObject obj = new JSONObject(userinfoJSON);
3.3 Yahoo
HttpGet getrequest = new HttpGet("https://social.yahooapis.com/v1/user/__USERID__/profile?format=json".replace("__USERID__", xoauth_yahoo_guid));getrequest.addHeader("Authorization", "Bearer " + access_token);
HttpResponse getresponse = httpclient.execute(getrequest);
String userinfoJSON = EntityUtils.toString(getresponse.getEntity());
final JSONObject profileobj = new JSONObject(userinfoJSON);
String yahooid = profileobj.getJSONObject("profile").getString("guid")
Step 4: automatic login in Spring Security
public static void autoLogin(
AuthenticationProvider authenticationProvider,
String oauthProvider,
OAuth2User oauth2User,
HttpServletRequest request) {
try {
Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();
grantedAuthorities.add(new GrantedAuthorityImpl("ROLE1"));
grantedAuthorities.add(new GrantedAuthorityImpl("ROLE2"));
// check if user is admin
if (adminIDs.contains(oauth2User.getID())) {
grantedAuthorities.add(new GrantedAuthorityImpl("admin"));
}
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("USER", "PASS", grantedAuthorities);
token.setDetails(new WebAuthenticationDetails(request));
Authentication authentication = authenticationProvider.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
// Create a new session and add the security context.
HttpSession session = request.getSession(true);
session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
} catch (Exception e) {
SecurityContextHolder.getContext().setAuthentication(null);
logger.error("Failure in autoLogin", e);
}
}
Hey Thanks very much for the post, can I have the complete source code please ?
ReplyDeleteAny example for Use Apache Httpclient to get access token from Twitter?
ReplyDelete