diff --git a/bundle b/bundle old mode 100755 new mode 100644 diff --git a/src/main/java/org/scribe/builder/ServiceBuilder.java b/src/main/java/org/scribe/builder/ServiceBuilder.java index 10d080282..4285ab5b5 100644 --- a/src/main/java/org/scribe/builder/ServiceBuilder.java +++ b/src/main/java/org/scribe/builder/ServiceBuilder.java @@ -21,6 +21,7 @@ public class ServiceBuilder private Api api; private String scope; private SignatureType signatureType; + private String grantType; /** * Default constructor @@ -137,6 +138,19 @@ public ServiceBuilder signatureType(SignatureType type) return this; } + /** + * Configures the grant type + * + * @param grant type + * @return the {@link ServiceBuilder} instance for method chaining + */ + public ServiceBuilder grantType(String grantType) + { + Preconditions.checkEmptyString(grantType, "Invalid OAuth Grant Type"); + this.grantType = grantType; + return this; + } + /** * Returns the fully configured {@link OAuthService} * @@ -147,6 +161,6 @@ public OAuthService build() Preconditions.checkNotNull(api, "You must specify a valid api through the provider() method"); Preconditions.checkEmptyString(apiKey, "You must provide an api key"); Preconditions.checkEmptyString(apiSecret, "You must provide an api secret"); - return api.createService(new OAuthConfig(apiKey, apiSecret, callback, signatureType, scope)); + return api.createService(new OAuthConfig(apiKey, apiSecret, callback, signatureType, scope,grantType)); } } diff --git a/src/main/java/org/scribe/builder/api/FacebookApi.java b/src/main/java/org/scribe/builder/api/FacebookApi.java index d85ff3b65..859bb4cba 100644 --- a/src/main/java/org/scribe/builder/api/FacebookApi.java +++ b/src/main/java/org/scribe/builder/api/FacebookApi.java @@ -9,11 +9,18 @@ public class FacebookApi extends DefaultApi20 { private static final String AUTHORIZE_URL = "https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s"; private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s"; + private static final String GRANT_TYPE_PARAM = "&grant_type=%s"; + + private static final String SCOPED_GRANT_TYPED_URL = SCOPED_AUTHORIZE_URL+GRANT_TYPE_PARAM; + private static final String GRANT_TYPED_URL = AUTHORIZE_URL + GRANT_TYPE_PARAM; + + private static final String ACCESS_TOKEN_ENDPOINT = "https://graph.facebook.com/oauth/access_token"; + @Override public String getAccessTokenEndpoint() { - return "https://graph.facebook.com/oauth/access_token"; + return ACCESS_TOKEN_ENDPOINT; } @Override @@ -21,10 +28,20 @@ public String getAuthorizationUrl(OAuthConfig config) { Preconditions.checkValidUrl(config.getCallback(), "Must provide a valid url as callback. Facebook does not support OOB"); - // Append scope if present - if(config.hasScope()) + // Append scope and/or grant type if present + if(config.hasScope() && !config.hasGrantType()) { - return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), formURLEncode(config.getCallback()), formURLEncode(config.getScope())); + return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(), formURLEncode(config.getCallback()), formURLEncode(config.getScope())); + } + else if(config.hasScope() && config.hasGrantType()) + { + return String.format(SCOPED_GRANT_TYPED_URL, config.getApiKey(),formURLEncode(config.getCallback()), + formURLEncode(config.getScope()),formURLEncode(config.getGrantType())); + } + else if(!config.hasScope() && config.hasGrantType()) + { + return String.format(GRANT_TYPED_URL, config.getApiKey(),formURLEncode(config.getCallback()), + formURLEncode(config.getGrantType())); } else { diff --git a/src/main/java/org/scribe/model/OAuthConfig.java b/src/main/java/org/scribe/model/OAuthConfig.java index 314d2d9b4..d9decda64 100644 --- a/src/main/java/org/scribe/model/OAuthConfig.java +++ b/src/main/java/org/scribe/model/OAuthConfig.java @@ -12,6 +12,7 @@ public class OAuthConfig private final String callback; private final SignatureType signatureType; private final String scope; + private final String grantType; public OAuthConfig(String key, String secret) { @@ -25,6 +26,17 @@ public OAuthConfig(String key, String secret, String callback, SignatureType typ this.callback = callback != null ? callback : OAuthConstants.OUT_OF_BAND; this.signatureType = (type != null) ? type : SignatureType.Header; this.scope = scope; + this.grantType = null; + } + + public OAuthConfig(String key, String secret, String callback, SignatureType type, String scope, String grantType) + { + this.apiKey = key; + this.apiSecret = secret; + this.callback = callback != null ? callback : OAuthConstants.OUT_OF_BAND; + this.signatureType = (type != null) ? type : SignatureType.Header; + this.scope = scope; + this.grantType = grantType; } public String getApiKey() @@ -51,9 +63,19 @@ public String getScope() { return scope; } + + public String getGrantType() + { + return grantType; + } public boolean hasScope() { return scope != null; } + + public boolean hasGrantType() + { + return grantType != null; + } } \ No newline at end of file diff --git a/src/main/java/org/scribe/model/OAuthConstants.java b/src/main/java/org/scribe/model/OAuthConstants.java index c93c31c71..dbf5ae50f 100644 --- a/src/main/java/org/scribe/model/OAuthConstants.java +++ b/src/main/java/org/scribe/model/OAuthConstants.java @@ -45,5 +45,11 @@ public class OAuthConstants public static final String CLIENT_SECRET = "client_secret"; public static final String REDIRECT_URI = "redirect_uri"; public static final String CODE = "code"; + public static final String GRANT_TYPE = "grant_type"; + // GrantType + public static final String AUTHORIZATION_CODE = "authorization_code"; + public static final String RESOURCE_OWNER_PASSWORD_CREDENTIALS = "password"; + public static final String CLIENT_CREDENTIALS = "client_credentials"; + public static final String REFRESH_TOKEN = "refresh_token"; } diff --git a/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java b/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java index 6262c3700..5fecdfde1 100644 --- a/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java +++ b/src/main/java/org/scribe/oauth/OAuth20ServiceImpl.java @@ -30,9 +30,11 @@ public Token getAccessToken(Token requestToken, Verifier verifier) OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint()); request.addQuerystringParameter(OAuthConstants.CLIENT_ID, config.getApiKey()); request.addQuerystringParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret()); - request.addQuerystringParameter(OAuthConstants.CODE, verifier.getValue()); + // In case of Client Credentials, verfier is not required + if(verifier != null) request.addQuerystringParameter(OAuthConstants.CODE, verifier.getValue()); request.addQuerystringParameter(OAuthConstants.REDIRECT_URI, config.getCallback()); if(config.hasScope()) request.addQuerystringParameter(OAuthConstants.SCOPE, config.getScope()); + if(config.hasGrantType()) request.addQuerystringParameter(OAuthConstants.GRANT_TYPE, config.getGrantType()); Response response = request.send(); return api.getAccessTokenExtractor().extract(response.getBody()); } diff --git a/src/test/java/org/scribe/builder/ServiceBuilderTest.java b/src/test/java/org/scribe/builder/ServiceBuilderTest.java index fca633be8..64b61e114 100644 --- a/src/test/java/org/scribe/builder/ServiceBuilderTest.java +++ b/src/test/java/org/scribe/builder/ServiceBuilderTest.java @@ -59,6 +59,15 @@ public void shouldAcceptAnScope() assertEquals(ApiMock.config.getApiSecret(), "secret"); assertEquals(ApiMock.config.getScope(), "rss-api"); } + @Test + public void shouldAcceptAGrantType() + { + builder.provider(ApiMock.class).apiKey("key").apiSecret("secret").grantType("client_credentials").build(); + assertEquals(ApiMock.config.getApiKey(), "key"); + assertEquals(ApiMock.config.getApiSecret(), "secret"); + assertEquals(ApiMock.config.getGrantType(), "client_credentials"); + } + public static class ApiMock implements Api { diff --git a/src/test/java/org/scribe/examples/FacebookAppLoginExample.java b/src/test/java/org/scribe/examples/FacebookAppLoginExample.java new file mode 100644 index 000000000..c4e6df770 --- /dev/null +++ b/src/test/java/org/scribe/examples/FacebookAppLoginExample.java @@ -0,0 +1,55 @@ +package org.scribe.examples; + +import org.scribe.builder.ServiceBuilder; +import org.scribe.builder.api.FacebookApi; +import org.scribe.model.OAuthConstants; +import org.scribe.model.OAuthRequest; +import org.scribe.model.Response; +import org.scribe.model.Token; +import org.scribe.model.Verb; +import org.scribe.oauth.OAuthService; + +public class FacebookAppLoginExample +{ + private static final String NETWORK_NAME = "Facebook"; + private static final Token EMPTY_TOKEN = null; + private static final String PROTECTED_RESOURCE_URL ="https://graph.facebook.com/%s/insights"; + + public static void main(String[] args) + { + // Replace these with your own api key and secret + + String apiKey = "your_app_id"; + String apiSecret = "your_api_secret"; + String callbackURL = "your_call_back"; + OAuthService service = new ServiceBuilder() + .provider(FacebookApi.class) + .apiKey(apiKey) + .apiSecret(apiSecret) + .callback(callbackURL) + .grantType(OAuthConstants.CLIENT_CREDENTIALS) + .build(); + + System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ==="); + System.out.println(); + System.out.println("Getting an access Token with Client Credentials (a.k.a App Login as Facebook defines)"); + Token accessToken = service.getAccessToken(EMPTY_TOKEN, null); + System.out.println("Got the Access Token!"); + System.out.println("(if your curious it looks like this: " + accessToken + " )"); + System.out.println(); + + // Now let's go and ask for a protected resource! + System.out.println("Now we're going to access a protected resource..."); + OAuthRequest request = new OAuthRequest(Verb.GET, String.format(PROTECTED_RESOURCE_URL,apiKey)); + service.signRequest(accessToken, request); + Response response = request.send(); + System.out.println("Got it! Lets see what we found..."); + System.out.println(); + System.out.println(response.getCode()); + System.out.println(response.getBody()); + + System.out.println(); + System.out.println("Thats it man! Go and build something awesome with Scribe! :)"); + + } +} diff --git a/src/test/java/org/scribe/model/OAuthConfigTest.java b/src/test/java/org/scribe/model/OAuthConfigTest.java index 973d40112..758d5296b 100644 --- a/src/test/java/org/scribe/model/OAuthConfigTest.java +++ b/src/test/java/org/scribe/model/OAuthConfigTest.java @@ -14,6 +14,7 @@ public void shouldReturnDefaultValuesIfNotSet() assertEquals(OAuthConstants.OUT_OF_BAND, config.getCallback()); assertEquals(SignatureType.Header, config.getSignatureType()); assertFalse(config.hasScope()); + assertFalse(config.hasGrantType()); } @Test