/framework/src/play/libs/OAuth2.java

http://github.com/playframework/play · Java · 192 lines · 125 code · 28 blank · 39 comment · 11 complexity · c89f9005ba26dce52222d8267982f212 MD5 · raw file

  1. package play.libs;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import com.google.gson.JsonElement;
  5. import com.google.gson.JsonObject;
  6. import play.libs.WS.HttpResponse;
  7. import play.mvc.Http.Request;
  8. import play.mvc.Scope.Params;
  9. import play.mvc.results.Redirect;
  10. /**
  11. * Library to access resources protected by OAuth 2.0. For OAuth 1.0a, see play.libs.OAuth. See the facebook-oauth2
  12. * example for usage.
  13. */
  14. public class OAuth2 {
  15. private static final String CLIENT_ID_NAME = "client_id";
  16. private static final String REDIRECT_URI = "redirect_uri";
  17. public String authorizationURL;
  18. public String accessTokenURL;
  19. public String clientid;
  20. public String secret;
  21. public OAuth2(String authorizationURL, String accessTokenURL, String clientid, String secret) {
  22. this.accessTokenURL = accessTokenURL;
  23. this.authorizationURL = authorizationURL;
  24. this.clientid = clientid;
  25. this.secret = secret;
  26. }
  27. public static boolean isCodeResponse() {
  28. return Params.current().get("code") != null;
  29. }
  30. /**
  31. * First step of the OAuth2 process: redirects the user to the authorisation page
  32. *
  33. * @param callbackURL
  34. * The callback URL
  35. */
  36. public void retrieveVerificationCode(String callbackURL) {
  37. retrieveVerificationCode(callbackURL, new HashMap<String, String>());
  38. }
  39. /**
  40. * First step of the oAuth2 process. This redirects the user to the authorization page on the oAuth2 provider. This
  41. * is a helper method that only takes one parameter name,value pair and then converts them into a map to be used by
  42. * {@link #retrieveVerificationCode(String, Map)}
  43. *
  44. * @param callbackURL
  45. * The URL to redirect the user to after authorization
  46. * @param parameterName
  47. * An additional parameter name
  48. * @param parameterValue
  49. * An additional parameter value
  50. */
  51. public void retrieveVerificationCode(String callbackURL, String parameterName, String parameterValue) {
  52. Map<String, String> parameters = new HashMap<>();
  53. parameters.put(parameterName, parameterValue);
  54. retrieveVerificationCode(callbackURL, parameters);
  55. }
  56. /**
  57. * First step of the oAuth2 process. This redirects the user to the authorisation page on the oAuth2 provider.
  58. *
  59. * @param callbackURL
  60. * The URL to redirect the user to after authorisation
  61. * @param parameters
  62. * Any additional parameters that weren't included in the constructor. For example you might need to add
  63. * a response_type.
  64. */
  65. public void retrieveVerificationCode(String callbackURL, Map<String, String> parameters) {
  66. parameters.put(CLIENT_ID_NAME, clientid);
  67. parameters.put(REDIRECT_URI, callbackURL);
  68. throw new Redirect(authorizationURL, parameters);
  69. }
  70. public void retrieveVerificationCode() {
  71. retrieveVerificationCode(Request.current().getBase() + Request.current().url);
  72. }
  73. public Response retrieveAccessToken(String callbackURL) {
  74. String accessCode = Params.current().get("code");
  75. Map<String, Object> params = new HashMap<>();
  76. params.put("client_id", clientid);
  77. params.put("client_secret", secret);
  78. params.put("redirect_uri", callbackURL);
  79. params.put("code", accessCode);
  80. HttpResponse response = WS.url(accessTokenURL).params(params).get();
  81. return new Response(response);
  82. }
  83. public Response retrieveAccessToken() {
  84. return retrieveAccessToken(Request.current().getBase() + Request.current().url);
  85. }
  86. /**
  87. * @deprecated Use @{link play.libs.OAuth2.retrieveVerificationCode()} instead
  88. */
  89. @Deprecated
  90. public void requestAccessToken() {
  91. retrieveVerificationCode();
  92. }
  93. /**
  94. * @return The access token
  95. * @deprecated Use @{link play.libs.OAuth2.retrieveAccessToken()} instead
  96. */
  97. @Deprecated
  98. public String getAccessToken() {
  99. return retrieveAccessToken().accessToken;
  100. }
  101. public static class Response {
  102. public final String accessToken;
  103. public final Error error;
  104. public final WS.HttpResponse httpResponse;
  105. private Response(String accessToken, Error error, WS.HttpResponse response) {
  106. this.accessToken = accessToken;
  107. this.error = error;
  108. this.httpResponse = response;
  109. }
  110. public Response(WS.HttpResponse response) {
  111. this.httpResponse = response;
  112. this.accessToken = getAccessToken(response);
  113. if (this.accessToken != null) {
  114. this.error = null;
  115. } else {
  116. this.error = Error.oauth2(response);
  117. }
  118. }
  119. public static Response error(Error error, WS.HttpResponse response) {
  120. return new Response(null, error, response);
  121. }
  122. private String getAccessToken(WS.HttpResponse httpResponse) {
  123. if (httpResponse.getContentType().contains("application/json")) {
  124. JsonElement accessToken = httpResponse.getJson().getAsJsonObject().get("access_token");
  125. return accessToken != null ? accessToken.getAsString() : null;
  126. } else {
  127. return httpResponse.getQueryString().get("access_token");
  128. }
  129. }
  130. }
  131. public static class Error {
  132. public final Type type;
  133. public final String error;
  134. public final String description;
  135. public enum Type {
  136. COMMUNICATION, OAUTH, UNKNOWN
  137. }
  138. private Error(Type type, String error, String description) {
  139. this.type = type;
  140. this.error = error;
  141. this.description = description;
  142. }
  143. static Error communication() {
  144. return new Error(Type.COMMUNICATION, null, null);
  145. }
  146. static Error oauth2(WS.HttpResponse response) {
  147. if (response.getQueryString().containsKey("error")) {
  148. Map<String, String> qs = response.getQueryString();
  149. return new Error(Type.OAUTH, qs.get("error"), qs.get("error_description"));
  150. } else if (response.getContentType().startsWith("text/javascript")) { // Stupid Facebook returns JSON with
  151. // the wrong encoding
  152. JsonObject jsonResponse = response.getJson().getAsJsonObject().getAsJsonObject("error");
  153. return new Error(Type.OAUTH, jsonResponse.getAsJsonPrimitive("type").getAsString(),
  154. jsonResponse.getAsJsonPrimitive("message").getAsString());
  155. } else {
  156. return new Error(Type.UNKNOWN, null, null);
  157. }
  158. }
  159. @Override
  160. public String toString() {
  161. return "OAuth2 Error: " + type + " - " + error + " (" + description + ")";
  162. }
  163. }
  164. }