Merged Diego's changes for OAuth2.0 server-side flow
This commit is contained in:
commit
c441b7d8a4
8 files changed
+152
-7
No files matched your search
+2
-1
@@ -29,4 +29,5 @@
|
||||
|
||||
* FIX: Removed isEmpty() from OAuth2.0 code in order to support older JVMs
|
||||
* FEATURE: Overloaded provider() method to support instances as well as classes (thanks dustismo)
|
||||
* FIX: White-space parameter bug (thanks Krogoth)
|
||||
* FIX: White-space parameter bug (thanks Krogoth)
|
||||
* FEATURE: OAuth 2.0 now implements server-flow (thanks Diego Silveira)
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.scribe.builder.api;
|
||||
|
||||
import org.scribe.extractors.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.oauth.*;
|
||||
|
||||
@@ -22,6 +23,33 @@ import org.scribe.oauth.*;
|
||||
public abstract class DefaultApi20 implements Api
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the access token extractor.
|
||||
*
|
||||
* @return access token extractor
|
||||
*/
|
||||
public AccessTokenExtractor getAccessTokenExtractor()
|
||||
{
|
||||
return new TokenExtractor20Impl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the verb for the access token endpoint (defaults to GET)
|
||||
*
|
||||
* @return access token endpoint verb
|
||||
*/
|
||||
public Verb getAccessTokenVerb()
|
||||
{
|
||||
return Verb.GET;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -5,8 +5,14 @@ import org.scribe.utils.*;
|
||||
|
||||
public class FacebookApi extends DefaultApi20
|
||||
{
|
||||
private static final String AUTHORIZE_URL = "https://graph.facebook.com/oauth/authorize?response_type=token&client_id=%s&redirect_uri=%s";
|
||||
private static final String AUTHORIZE_URL = "https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s";
|
||||
|
||||
@Override
|
||||
public String getAccessTokenEndpoint()
|
||||
{
|
||||
return "https://graph.facebook.com/oauth/access_token";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthorizationUrl(OAuthConfig config)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.scribe.extractors;
|
||||
|
||||
import java.util.regex.*;
|
||||
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
import org.scribe.utils.*;
|
||||
|
||||
/**
|
||||
* Default implementation of {@AccessTokenExtractor}. Conforms to OAuth 2.0
|
||||
*
|
||||
*/
|
||||
public class TokenExtractor20Impl implements AccessTokenExtractor
|
||||
{
|
||||
private static final String TOKEN_REGEX = "access_token=(\\S*?)(&(\\S*))?";
|
||||
private static final String EMPTY_SECRET = "";
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Token extract(String response)
|
||||
{
|
||||
Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string");
|
||||
|
||||
Matcher matcher = Pattern.compile(TOKEN_REGEX).matcher(response);
|
||||
if (matcher.matches())
|
||||
{
|
||||
String token = URLUtils.percentDecode(matcher.group(1));
|
||||
return new Token(token, EMPTY_SECRET);
|
||||
} else
|
||||
{
|
||||
throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,4 +41,9 @@ public class OAuthConstants
|
||||
|
||||
//OAuth 2.0
|
||||
public static final String ACCESS_TOKEN = "access_token";
|
||||
public static final String CLIENT_ID = "client_id";
|
||||
public static final String CLIENT_SECRET = "client_secret";
|
||||
public static final String REDIRECT_URI = "redirect_uri";
|
||||
public static final String CODE = "code";
|
||||
|
||||
}
|
||||
@@ -35,7 +35,13 @@ public class OAuth20ServiceImpl implements OAuthService
|
||||
*/
|
||||
public Token getAccessToken(Token requestToken, Verifier verifier)
|
||||
{
|
||||
throw new UnsupportedOperationException("Unsupported operation, please use 'getAuthorizationUrl' and redirect your users there");
|
||||
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());
|
||||
request.addQuerystringParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
|
||||
Response response = request.send();
|
||||
return api.getAccessTokenExtractor().extract(response.getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,13 +11,12 @@ public class FacebookExample
|
||||
{
|
||||
private static final String NETWORK_NAME = "Facebook";
|
||||
private static final String PROTECTED_RESOURCE_URL = "https://graph.facebook.com/me";
|
||||
private static final String NO_SECRET_NEEDED = "";
|
||||
private static final Token EMPTY_TOKEN = null;
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// Replace these with your own api key and secret
|
||||
String apiKey = "your_api_key";
|
||||
String apiKey = "your_app_id";
|
||||
String apiSecret = "your_api_secret";
|
||||
OAuthService service = new ServiceBuilder()
|
||||
.provider(FacebookApi.class)
|
||||
@@ -36,9 +35,16 @@ public class FacebookExample
|
||||
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 access token here");
|
||||
System.out.println("And paste the authorization code here");
|
||||
System.out.print(">>");
|
||||
Token accessToken = new Token(in.nextLine(), NO_SECRET_NEEDED);
|
||||
Verifier verifier = new Verifier(in.nextLine());
|
||||
System.out.println();
|
||||
|
||||
// Trade the Request Token and Verfier for the Access Token
|
||||
System.out.println("Trading the Request Token for an Access Token...");
|
||||
Token accessToken = service.getAccessToken(EMPTY_TOKEN, verifier);
|
||||
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!
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.scribe.extractors;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.*;
|
||||
import org.scribe.exceptions.*;
|
||||
import org.scribe.model.*;
|
||||
|
||||
public class TokenExtractor20Test
|
||||
{
|
||||
|
||||
private TokenExtractor20Impl extractor;
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
{
|
||||
extractor = new TokenExtractor20Impl();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractTokenFromOAuthStandardResponse()
|
||||
{
|
||||
String response = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE";
|
||||
Token extracted = extractor.extract(response);
|
||||
assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", extracted.getToken());
|
||||
assertEquals("", extracted.getSecret());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExtractTokenFromResponseWithExpiresParam()
|
||||
{
|
||||
String response = "access_token=166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE&expires=5108";
|
||||
Token extracted = extractor.extract(response);
|
||||
assertEquals("166942940015970|2.2ltzWXYNDjCtg5ZDVVJJeg__.3600.1295816400-548517159|RsXNdKrpxg8L6QNLWcs2TVTmcaE", extracted.getToken());
|
||||
assertEquals("", extracted.getSecret());
|
||||
}
|
||||
|
||||
@Test(expected = OAuthException.class)
|
||||
public void shouldThrowExceptionIfTokenIsAbsent()
|
||||
{
|
||||
String response = "&expires=5108";
|
||||
extractor.extract(response);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionIfResponseIsNull()
|
||||
{
|
||||
String response = null;
|
||||
extractor.extract(response);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void shouldThrowExceptionIfResponseIsEmptyString()
|
||||
{
|
||||
String response = "";
|
||||
extractor.extract(response);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user