From 3d098acb58c07f889238a903c66d0444bb4cef29 Mon Sep 17 00:00:00 2001 From: Cas S Date: Tue, 27 Dec 2011 21:18:14 -0500 Subject: [PATCH] Changes to add GooglePlus --- pom.xml | 40 ++++++++- .../org/scribe/builder/api/DefaultApi20a.java | 69 ++++++++++++++++ .../org/scribe/builder/api/GooglePlusApi.java | 36 +++++++++ .../scribe/examples/GooglePlusExample.java | 81 +++++++++++++++++++ .../scribe/extractors/JsonTokenExtractor.java | 1 - .../org/scribe/oauth/OAuth20aServiceImpl.java | 73 +++++++++++++++++ 6 files changed, 296 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/scribe/builder/api/DefaultApi20a.java create mode 100644 src/main/java/org/scribe/builder/api/GooglePlusApi.java create mode 100644 src/main/java/org/scribe/examples/GooglePlusExample.java create mode 100644 src/main/java/org/scribe/oauth/OAuth20aServiceImpl.java diff --git a/pom.xml b/pom.xml index a3b01964f..1058d0e32 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,13 @@ diegossilveira@gmail.com -3 + + ezgraphs + C S + ezgraphs@gmail.com + -3 + + @@ -56,17 +63,43 @@ 4.8.1 test + + + + com.google.code.gson + gson + 1.7.1 + compile + + - - - + + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + java + + -classpath + + org.scribe.examples.GooglePlusExample + + + + + + maven-compiler-plugin 1.5 1.5 + diff --git a/src/main/java/org/scribe/builder/api/DefaultApi20a.java b/src/main/java/org/scribe/builder/api/DefaultApi20a.java new file mode 100644 index 000000000..6696abcef --- /dev/null +++ b/src/main/java/org/scribe/builder/api/DefaultApi20a.java @@ -0,0 +1,69 @@ +package org.scribe.builder.api; + +import org.scribe.extractors.*; +import org.scribe.model.*; +import org.scribe.oauth.*; + +/** + * Default implementation of the OAuth protocol, version 2.0 (draft 11) + * + * This class is meant to be extended by concrete implementations of the API, + * providing the endpoints and endpoint-http-verbs. + * + * If your Api adheres to the 2.0 (draft 11) protocol correctly, you just need to extend + * this class and define the getters for your endpoints. + * + * If your Api does something a bit different, you can override the different + * extractors or services, in order to fine-tune the process. Please read the + * javadocs of the interfaces to get an idea of what to do. + * + * @author Diego Silveira + * + */ +public abstract class DefaultApi20a extends DefaultApi20 implements Api +{ + + /** + * Returns the access token extractor. + * + * @return json token extractor + */ + public AccessTokenExtractor getAccessTokenExtractor() { + return new JsonTokenExtractor(); + } + + /** + * Returns the verb for the access token endpoint (defaults to GET) + * + * @return access token endpoint verb + */ + public Verb getAccessTokenVerb() + { + return Verb.POST; + } + + /** + * Returns the URL that receives the access token requests. + * + * @return access token URL + */ + public abstract String getAccessTokenEndpoint(); + + /** + * Returns the URL where you should redirect your users to authenticate + * your application. + * + * @param config OAuth 2.0 configuration param object + * @return the URL where you should redirect your users + */ + public abstract String getAuthorizationUrl(OAuthConfig config); + + /** + * {@inheritDoc} + */ + public OAuthService createService(OAuthConfig config) + { + return new OAuth20aServiceImpl(this, config); + } + +} diff --git a/src/main/java/org/scribe/builder/api/GooglePlusApi.java b/src/main/java/org/scribe/builder/api/GooglePlusApi.java new file mode 100644 index 000000000..83e930ed1 --- /dev/null +++ b/src/main/java/org/scribe/builder/api/GooglePlusApi.java @@ -0,0 +1,36 @@ +package org.scribe.builder.api; + +import org.scribe.builder.api.DefaultApi20a; +import org.scribe.extractors.AccessTokenExtractor; +import org.scribe.extractors.JsonTokenExtractor; +import org.scribe.model.OAuthConfig; +import org.scribe.model.Verb; +import org.scribe.utils.OAuthEncoder; + +/** + * User: ezgraphs + * Date: 12/27/11 + * Time: 8:54 AM + */ +public class GooglePlusApi extends DefaultApi20a { + + private static final String BASE_URL = "https://accounts.google.com/o/oauth2"; + private static final String AUTHORIZE_URL = BASE_URL + "/auth?response_type=code&client_id=%s&scope=%s&redirect_uri=%s"; + + + @Override + public String getAccessTokenEndpoint() { + + return BASE_URL + "/token"; + } + + @Override + public AccessTokenExtractor getAccessTokenExtractor() { + return new JsonTokenExtractor(); + } + + @Override + public String getAuthorizationUrl(OAuthConfig config) { + return String.format(AUTHORIZE_URL, config.getApiKey(), OAuthEncoder.encode(config.getScope()), OAuthEncoder.encode(config.getCallback())); + } +} diff --git a/src/main/java/org/scribe/examples/GooglePlusExample.java b/src/main/java/org/scribe/examples/GooglePlusExample.java new file mode 100644 index 000000000..e91822139 --- /dev/null +++ b/src/main/java/org/scribe/examples/GooglePlusExample.java @@ -0,0 +1,81 @@ +package org.scribe.examples; + +import com.google.gson.*; +import java.util.*; +import org.scribe.builder.*; +import org.scribe.builder.api.*; +import org.scribe.model.*; +import org.scribe.oauth.*; + +// https://developers.google.com/+/api/ +// https://developers.google.com/+/api/latest/people/get#try-it +// http://code.google.com/apis/accounts/docs/OAuth2WebServer.html#callinganapi + +// https://code.google.com/apis/console/#project:419708088990:quotas +// https://code.google.com/apis/console/#project:419708088990:access +// http://sites.google.com/site/gson/gson-user-guide#TOC-Overview + +public class GooglePlusExample{ + + public static void main(String args[]) throws Exception { + + String apiKey = "419708088990.apps.googleusercontent.com"; + String secret = "tNpXobmvQ3tM2234BW2OsjXT"; + String callback = "http://www.r-chart.com"; + String scope = "https://www.googleapis.com/auth/plus.me"; + + OAuthService service = new ServiceBuilder() + .provider(GooglePlusApi.class) + .apiKey(apiKey) + .apiSecret(secret) + .callback(callback) + .scope(scope) + .build(); + + Scanner in = new Scanner(System.in); + + System.out.println("Fetching the Authorization URL..."); + String authorizationUrl = service.getAuthorizationUrl(null); + System.out.println("Got the Authorization URL!"); + System.out.println("Now go and authorize Scribe here:"); + System.out.println(authorizationUrl); + System.out.println("And paste the authorization code here"); + System.out.print(">>"); + String code = in.nextLine(); + + Verifier verifier = new Verifier(code); + System.out.println("Trading the Request Token for an Access Token..."); + + Token accessToken = service.getAccessToken(null, verifier); + + System.out.println("Now we're going to access a protected resource...creating request"); + String url = "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + accessToken.getToken(); + System.out.println("Trying userInfo url: " + url); + OAuthRequest request = new OAuthRequest(Verb.GET, url); + + System.out.println("Sending request... getting response"); + + Response response = request.send(); + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + String b = response.getBody(); + System.out.println(b); + + String id = extractId(b); + System.out.println("Sending request... getting response"); + request = new OAuthRequest(Verb.GET, "https://www.googleapis.com/plus/v1/people/me?access_token=" + accessToken.getToken()); + response = request.send(); + System.out.println("Got it! Lets see what we found..."); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + + } + + public static String extractId(String body) { + JsonParser parser = new JsonParser(); + JsonElement e = parser.parse(body); + return e.getAsJsonObject().get("id").getAsString(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/scribe/extractors/JsonTokenExtractor.java b/src/main/java/org/scribe/extractors/JsonTokenExtractor.java index 7c1ee04e1..5bec42379 100644 --- a/src/main/java/org/scribe/extractors/JsonTokenExtractor.java +++ b/src/main/java/org/scribe/extractors/JsonTokenExtractor.java @@ -10,7 +10,6 @@ public class JsonTokenExtractor implements AccessTokenExtractor { private Pattern accessTokenPattern = Pattern.compile("\"access_token\":\\s*\"(\\S*?)\""); - @Override public Token extract(String response) { Preconditions.checkEmptyString(response, "Cannot extract a token from a null or empty String"); diff --git a/src/main/java/org/scribe/oauth/OAuth20aServiceImpl.java b/src/main/java/org/scribe/oauth/OAuth20aServiceImpl.java new file mode 100644 index 000000000..6bb9a1184 --- /dev/null +++ b/src/main/java/org/scribe/oauth/OAuth20aServiceImpl.java @@ -0,0 +1,73 @@ +package org.scribe.oauth; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import org.scribe.builder.api.DefaultApi20a; +import org.scribe.builder.api.DefaultApi20; +import org.scribe.model.OAuthConfig; +import org.scribe.model.OAuthConstants; +import org.scribe.model.OAuthRequest; +import org.scribe.model.Response; +import org.scribe.model.Token; +import org.scribe.model.Verifier; +import org.scribe.oauth.OAuth20ServiceImpl; +import org.scribe.oauth.OAuthService; + +/** + * User: ezgraphs + * Date: 12/27/11 + * Time: 11:16 AM + */ +public class OAuth20aServiceImpl extends OAuth20ServiceImpl implements OAuthService { + + private final DefaultApi20a api; + private final OAuthConfig config; + + /** + * Replicate api and config variables and assignment + * since the superclass declares these private + * + * @param api + * @param config + */ + public OAuth20aServiceImpl(DefaultApi20 api, OAuthConfig config) { + super(api, config); + this.api = (DefaultApi20a) api; + this.config = config; + } + + /** + * The method overwritten below was required because parameters are body parameters in the + * Google version of the API. In addition, a body parameter of type grant_type is needed. + * + * {@inheritDoc} + */ + public Token getAccessToken(Token requestToken, Verifier verifier) { + OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); + + request.addBodyParameter("grant_type", "authorization_code"); + request.addBodyParameter(OAuthConstants.CODE, verifier.getValue()); + request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey()); + request.addBodyParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret()); + request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback()); + if (config.hasScope()) request.addBodyParameter(OAuthConstants.SCOPE, config.getScope()); + Response response = request.send(); + String body = response.getBody(); + System.out.println("body:\n" + body); + return extract(body); + } + + /** + * @param body + * + * @return + */ + private Token extract(String body) { + JsonParser parser = new JsonParser(); + JsonElement e = parser.parse(body); + + String accessToken = e.getAsJsonObject().get("access_token").getAsString(); + String id = e.getAsJsonObject().get("id_token").getAsString(); + return new Token(accessToken, id); + } +} \ No newline at end of file