Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Added OAuth2 support and examples for Twitter API#1001

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
xiangyao1989 wants to merge1 commit intoscribejava:master
base:master
Choose a base branch
Loading
fromxiangyao1989:twitter-oauth2
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletionsREADME.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -104,6 +104,7 @@ ScribeJava support out-of-box several HTTP clients:
* Tumblr (https://www.tumblr.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TumblrExample.java)
* TUT.BY (http://www.tut.by/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TutByExample.java)
* Twitter (https://twitter.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TwitterExample.java)
* Twitter 2.0 (https://twitter.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Twitter20WithPKCEExample.java)
* uCoz (https://www.ucoz.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/UcozExample.java)
* Viadeo (http://viadeo.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/ViadeoExample.java)
* VK ВКонтакте (http://vk.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExample.java), [example Client Credentials Grant](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteClientCredentialsGrantExample.java), [example with External HTTP Client](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/VkontakteExternalHttpExample.java)
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
package com.github.scribejava.apis;

import com.github.scribejava.apis.openid.OpenIdJsonTokenExtractor;
import com.github.scribejava.core.builder.api.DefaultApi20;
import com.github.scribejava.core.extractors.TokenExtractor;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication;
import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme;

public class TwitterApi20 extends DefaultApi20 {

protected TwitterApi20() {
}

private static class InstanceHolder {

private static final TwitterApi20 INSTANCE = new TwitterApi20();
}

public static TwitterApi20 instance() {
return InstanceHolder.INSTANCE;
}

@Override
public String getAccessTokenEndpoint() {
return "https://api.twitter.com/2/oauth2/token";
}

@Override
protected String getAuthorizationBaseUrl() {
return "https://developer.twitter.com/2/oauth2/consent";
}

@Override
public TokenExtractor<OAuth2AccessToken> getAccessTokenExtractor() {
return OpenIdJsonTokenExtractor.instance();
}

@Override
public String getRevokeTokenEndpoint() {
return "https://api.twitter.com/2/oauth2/revoke";
}

@Override
public ClientAuthentication getClientAuthentication() {
return RequestBodyAuthenticationScheme.instance();
}
}
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
package com.github.scribejava.apis.examples;

import java.util.Random;
import java.util.Scanner;

import com.github.scribejava.apis.TwitterApi20;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.oauth.AuthorizationUrlBuilder;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.github.scribejava.core.model.OAuthRequest;
import com.github.scribejava.core.model.Response;
import com.github.scribejava.core.model.Verb;
import com.github.scribejava.core.oauth.AccessTokenRequestParams;
import com.github.scribejava.core.oauth.OAuth20Service;
import com.github.scribejava.core.revoke.TokenTypeHint;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

public class Twitter20WithPKCEExample {

private static final String NETWORK_NAME = "Twitter";
private static final String PROTECTED_RESOURCE_URL = "https://api.twitter.com/2/tweets?ids=1261326399320715264,1278347468690915330";

private Twitter20WithPKCEExample() {
}

@SuppressWarnings("PMD.SystemPrintln")
public static void main(String... args) throws IOException, InterruptedException, ExecutionException {
final String clientId = "CLIENT_ID"; // replace these with your client id
final String state = "secret" + new Random().nextInt(999_999);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I detect that this code is problematic. According to theBad practice (BAD_PRACTICE),DMI: Random object created and used only once (DMI_RANDOM_USED_ONLY_ONCE).
This code creates a java.util.Random object, uses it to generate one random number, and then discards the Random object. This produces mediocre quality random numbers and is inefficient. If possible, rewrite the code so that the Random object is created once and saved, and each time a new random number is required invoke a method on the existing Random object to obtain it.
If it is important that the generated Random numbers not be guessable, youmust not create a new Random for each random number; the values are too easily guessable. You should strongly consider using a java.security.SecureRandom instead (and avoid allocating a new SecureRandom for each random number needed).

final OAuth20Service service = new ServiceBuilder(clientId)
.defaultScope("tweet.read users.read account.follows.read account.follows.write") // replace with desired scope
.callback("https://twitter.com/")
.build(TwitterApi20.instance());

final Scanner in = new Scanner(System.in, "UTF-8");

System.out.println("=== " + NETWORK_NAME + "'s OAuth Workflow ===");
System.out.println();

// Obtain the Authorization URL
System.out.println("Fetching the Authorization URL...");
final Map<String, String> additionalParams = new HashMap<>();

final AuthorizationUrlBuilder authorizationUrlBuilder = service.createAuthorizationUrlBuilder()
.state(state)
.additionalParams(additionalParams)
.initPKCE();

System.out.println("Got the Authorization URL!");
System.out.println("Now go and authorize ScribeJava here:");
System.out.println(authorizationUrlBuilder.build());
System.out.println("And paste the authorization code here");
System.out.print(">>");
final String code = in.nextLine();
System.out.println();

System.out.println("And paste the state from server here. We have set 'state'='" + state + "'.");
System.out.print(">>");
final String value = in.nextLine();
if (state.equals(value)) {
System.out.println("State value does match!");
} else {
System.out.println("Ooops, state value does not match!");
System.out.println("Expected = " + state);
System.out.println("Got = " + value);
System.out.println();
}

System.out.println("Trading the Authorization Code for an Access Token...");
OAuth2AccessToken accessToken = service.getAccessToken(AccessTokenRequestParams.create(code).clientId(clientId)
.pkceCodeVerifier(authorizationUrlBuilder.getPkce().getCodeVerifier()));
System.out.println("Got the Access Token!");
System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')");

fetchResource(service, accessToken, PROTECTED_RESOURCE_URL);

System.out.println("Refreshing the Access Token...");
accessToken = service.refreshAccessToken(accessToken.getRefreshToken(), null, clientId);
System.out.println("Refreshed the Access Token!");
System.out.println("(The raw response looks like this: " + accessToken.getRawResponse() + "')");
System.out.println();

fetchResource(service, accessToken, PROTECTED_RESOURCE_URL);

System.out.println("Revoking the Refresh Token...");
service.revokeToken(accessToken.getRefreshToken(), TokenTypeHint.REFRESH_TOKEN);
System.out.println("Revoked the Refresh Token!");
// Access Token is still valid
fetchResource(service, accessToken, PROTECTED_RESOURCE_URL);

System.out.println("Revoking the Access Token...");
service.revokeToken(accessToken.getAccessToken(), TokenTypeHint.ACCESS_TOKEN);
System.out.println("Revoked the Access Token!");
// Both Access Token and Refresh Token are revoked at this moment
fetchResource(service, accessToken, PROTECTED_RESOURCE_URL);

// Now let's go and ask for a protected resource!
while (true) {
System.out.println("Paste fieldnames to fetch (leave empty to get profile, 'exit' to stop example)");
System.out.print(">>");
final String query = in.nextLine();
System.out.println();

final String requestUrl;
if ("exit".equals(query)) {
break;
} else if (query == null || query.isEmpty()) {
requestUrl = PROTECTED_RESOURCE_URL;
} else {
requestUrl = PROTECTED_RESOURCE_URL + "?fields=" + query;
}
fetchResource(service, accessToken, requestUrl);
}
}

private static void fetchResource(OAuth20Service service, OAuth2AccessToken accessToken, String requestUrl)
throws IOException, InterruptedException, ExecutionException {
// Now let's go and ask for a protected resource!
System.out.println();
System.out.println("Now we're going to access a protected resource...");
final OAuthRequest request = new OAuthRequest(Verb.GET, requestUrl);
service.signRequest(accessToken, request);
try (Response response = service.execute(request)) {
System.out.println(response.getCode());
System.out.println(response.getBody());
}
System.out.println();
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,6 +7,7 @@ public class AccessTokenRequestParams {
private final String code;
private String pkceCodeVerifier;
private String scope;
private String clientId;

public AccessTokenRequestParams(String code) {
this.code = code;
Expand All@@ -21,13 +22,18 @@ public AccessTokenRequestParams pkceCodeVerifier(String pkceCodeVerifier) {
return this;
}

public AccessTokenRequestParams scope(ScopeBuilder scope) {
this.scope = scope.build();
return this;
}

public AccessTokenRequestParams scope(String scope) {
this.scope = scope;
return this;
}

public AccessTokenRequestParamsscope(ScopeBuilder scope) {
this.scope =scope.build();
public AccessTokenRequestParamsclientId(String clientId) {
this.clientId =clientId;
return this;
}

Expand All@@ -42,4 +48,8 @@ public String getPkceCodeVerifier() {
public String getScope() {
return scope;
}

public String getClientId() {
return clientId;
}
}
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -140,6 +140,14 @@ protected OAuthRequest createAccessTokenRequest(AccessTokenRequestParams params)
if (pkceCodeVerifier != null) {
request.addParameter(PKCE.PKCE_CODE_VERIFIER_PARAM, pkceCodeVerifier);
}

final String clientId = params.getClientId();
if (clientId != null) {
// OAuth2 token endpoint may require client id
// https://www.oauth.com/oauth2-servers/access-tokens/authorization-code-request/
request.addParameter(OAuthConstants.CLIENT_ID, clientId);
}

logRequestWithParams("access token", request);
return request;
}
Expand All@@ -149,7 +157,7 @@ public Future<OAuth2AccessToken> refreshAccessTokenAsync(String refreshToken) {
}

public Future<OAuth2AccessToken> refreshAccessTokenAsync(String refreshToken, String scope) {
return refreshAccessToken(refreshToken, scope, null);
return refreshAccessToken(refreshToken, scope,(OAuthAsyncRequestCallback<OAuth2AccessToken>)null);
}

public OAuth2AccessToken refreshAccessToken(String refreshToken)
Expand All@@ -159,26 +167,33 @@ public OAuth2AccessToken refreshAccessToken(String refreshToken)

public OAuth2AccessToken refreshAccessToken(String refreshToken, String scope)
throws IOException, InterruptedException, ExecutionException {
final OAuthRequest request = createRefreshTokenRequest(refreshToken, scope);
final OAuthRequest request = createRefreshTokenRequest(refreshToken, scope, null);

return sendAccessTokenRequestSync(request);
}

public OAuth2AccessToken refreshAccessToken(String refreshToken, String scope, String clientId)
throws IOException, InterruptedException, ExecutionException {
final OAuthRequest request = createRefreshTokenRequest(refreshToken, scope, clientId);

return sendAccessTokenRequestSync(request);
}

public Future<OAuth2AccessToken> refreshAccessToken(String refreshToken,
OAuthAsyncRequestCallback<OAuth2AccessToken> callback) {
final OAuthRequest request = createRefreshTokenRequest(refreshToken, null);
final OAuthRequest request = createRefreshTokenRequest(refreshToken, null, null);

return sendAccessTokenRequestAsync(request, callback);
}

public Future<OAuth2AccessToken> refreshAccessToken(String refreshToken, String scope,
OAuthAsyncRequestCallback<OAuth2AccessToken> callback) {
final OAuthRequest request = createRefreshTokenRequest(refreshToken, scope);
final OAuthRequest request = createRefreshTokenRequest(refreshToken, scope, null);

return sendAccessTokenRequestAsync(request, callback);
}

protected OAuthRequest createRefreshTokenRequest(String refreshToken, String scope) {
protected OAuthRequest createRefreshTokenRequest(String refreshToken, String scope, String clientId) {
if (refreshToken == null || refreshToken.isEmpty()) {
throw new IllegalArgumentException("The refreshToken cannot be null or empty");
}
Expand All@@ -195,6 +210,12 @@ protected OAuthRequest createRefreshTokenRequest(String refreshToken, String sco
request.addParameter(OAuthConstants.REFRESH_TOKEN, refreshToken);
request.addParameter(OAuthConstants.GRANT_TYPE, OAuthConstants.REFRESH_TOKEN);

if (clientId != null) {
// OAuth2 token endpoint may require client id
// https://www.oauth.com/oauth2-servers/access-tokens/authorization-code-request/
request.addParameter(OAuthConstants.CLIENT_ID, clientId);
}

logRequestWithParams("refresh token", request);

return request;
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp