package play.libs; import java.util.HashMap; import java.util.Map; import play.mvc.Http.Request; import play.mvc.Scope.Params; import play.mvc.results.Redirect; import play.libs.WS.HttpResponse; import com.google.gson.JsonObject; /** * Library to access ressources protected by OAuth 2.0. For OAuth 1.0a, see play.libs.OAuth. * See the facebook-oauth2 example for usage. * */ public class OAuth2 { public String authorizationURL; public String accessTokenURL; public String clientid; public String secret; public OAuth2(String authorizationURL, String accessTokenURL, String clientid, String secret) { this.accessTokenURL = accessTokenURL; this.authorizationURL = authorizationURL; this.clientid = clientid; this.secret = secret; } public static boolean isCodeResponse() { return Params.current().get("code") != null; } /** * First step of the OAuth2 process: redirects the user to the authorization page * * @param callbackURL */ public void retrieveVerificationCode(String callbackURL) { throw new Redirect(authorizationURL + "?client_id=" + clientid + "&redirect_uri=" + callbackURL); } public void retrieveVerificationCode() { retrieveVerificationCode(Request.current().getBase() + Request.current().url); } public Response retrieveAccessToken(String callbackURL) { String accessCode = Params.current().get("code"); Map<String, Object> params = new HashMap<String, Object>(); params.put("client_id", clientid); params.put("client_secret", secret); params.put("redirect_uri", callbackURL); params.put("code", accessCode); HttpResponse response = WS.url(accessTokenURL).params(params).get(); return new Response(response); } public Response retrieveAccessToken() { return retrieveAccessToken(Request.current().getBase() + Request.current().url); } /** * @deprecated Use @{link play.libs.OAuth2.retrieveVerificationCode()} instead */ @Deprecated public void requestAccessToken() { retrieveVerificationCode(); } /** * @deprecated Use @{link play.libs.OAuth2.retrieveAccessToken()} instead */ @Deprecated public String getAccessToken() { return retrieveAccessToken().accessToken; } public static class Response { public final String accessToken; public final Error error; public final WS.HttpResponse httpResponse; private Response(String accessToken, Error error, WS.HttpResponse response) { this.accessToken = accessToken; this.error = error; this.httpResponse = response; } public Response(WS.HttpResponse response) { this.httpResponse = response; Map<String, String> querystring = response.getQueryString(); if (querystring.containsKey("access_token")) { this.accessToken = querystring.get("access_token"); this.error = null; } else { this.accessToken = null; this.error = Error.oauth2(response); } } public static Response error(Error error, WS.HttpResponse response) { return new Response(null, error, response); } } public static class Error { public final Type type; public final String error; public final String description; public enum Type { COMMUNICATION, OAUTH, UNKNOWN } private Error(Type type, String error, String description) { this.type = type; this.error = error; this.description = description; } static Error communication() { return new Error(Type.COMMUNICATION, null, null); } static Error oauth2(WS.HttpResponse response) { if (response.getQueryString().containsKey("error")) { Map<String, String> qs = response.getQueryString(); return new Error(Type.OAUTH, qs.get("error"), qs.get("error_description")); } else if (response.getContentType().startsWith("text/javascript")) { // Stupid Facebook returns JSON with the wrong encoding JsonObject jsonResponse = response.getJson().getAsJsonObject().getAsJsonObject("error"); return new Error(Type.OAUTH, jsonResponse.getAsJsonPrimitive("type").getAsString(), jsonResponse.getAsJsonPrimitive("message").getAsString()); } else { return new Error(Type.UNKNOWN, null, null); } } @Override public String toString() { return "OAuth2 Error: " + type + " - " + error + " (" + description + ")"; } } }