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

Commit08d6ecb

Browse files
committed
add support for OAuth 2.0 Device Authorization Grant (RFC 8628) (thanks tohttps://github.com/rebarbora-mckvak)
1 parent50e7c96 commit08d6ecb

File tree

15 files changed

+496
-166
lines changed

15 files changed

+496
-166
lines changed

‎README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ ScribeJava support out-of-box several HTTP clients:
5050
*[RFC 6750](https://tools.ietf.org/html/rfc6750) The OAuth 2.0 Authorization Framework: Bearer Token Usage
5151
*[RFC 7636](https://tools.ietf.org/html/rfc7636) Proof Key for Code Exchange by OAuth Public Clients (PKCE),[example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20WithPKCEExample.java)
5252
*[RFC 7009](https://tools.ietf.org/html/rfc7009) OAuth 2.0 Token Revocation,[example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20RevokeExample.java)
53+
*[RFC 8628](https://tools.ietf.org/html/rfc8628) OAuth 2.0 Device Authorization Grant[example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20DeviceAuthorizationGrantExample.java)
5354
*[RFC 5849](https://tools.ietf.org/html/rfc5849) The OAuth 1.0 Protocol,[example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/TwitterExample.java)
5455

5556
###Supports all (50+) major 1.0a and 2.0 OAuth APIs out-of-the-box

‎changelog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[SNAPSHOT]
22
* add Kakao API (https://kakao.com/) (thanks to https://github.com/v0o0v)
33
* support chunks in JDKHttpClient's Multipart (thanks to https://github.com/eos1d3)
4+
* add support for OAuth 2.0 Device Authorization Grant (RFC 8628) (thanks to https://github.com/rebarbora-mckvak)
45

56
[7.1.1]
67
* add Proxy support (via config's option) to internal JDKHttpClient (thanks to https://github.com/bjournaud)

‎scribejava-apis/src/main/java/com/github/scribejava/apis/GoogleApi20.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
packagecom.github.scribejava.apis;
22

3+
importcom.github.scribejava.apis.google.GoogleDeviceAuthorizationJsonExtractor;
34
importcom.github.scribejava.apis.openid.OpenIdJsonTokenExtractor;
45
importcom.github.scribejava.core.builder.api.DefaultApi20;
6+
importcom.github.scribejava.core.extractors.DeviceAuthorizationJsonExtractor;
57
importcom.github.scribejava.core.extractors.TokenExtractor;
68
importcom.github.scribejava.core.model.OAuth2AccessToken;
79

@@ -11,6 +13,7 @@ protected GoogleApi20() {
1113
}
1214

1315
privatestaticclassInstanceHolder {
16+
1417
privatestaticfinalGoogleApi20INSTANCE =newGoogleApi20();
1518
}
1619

@@ -20,12 +23,12 @@ public static GoogleApi20 instance() {
2023

2124
@Override
2225
publicStringgetAccessTokenEndpoint() {
23-
return"https://www.googleapis.com/oauth2/v4/token";
26+
return"https://oauth2.googleapis.com/token";
2427
}
2528

2629
@Override
2730
protectedStringgetAuthorizationBaseUrl() {
28-
return"https://accounts.google.com/o/oauth2/auth";
31+
return"https://accounts.google.com/o/oauth2/v2/auth";
2932
}
3033

3134
@Override
@@ -35,6 +38,16 @@ public TokenExtractor<OAuth2AccessToken> getAccessTokenExtractor() {
3538

3639
@Override
3740
publicStringgetRevokeTokenEndpoint() {
38-
return"https://accounts.google.com/o/oauth2/revoke";
41+
return"https://oauth2.googleapis.com/revoke";
42+
}
43+
44+
@Override
45+
publicStringgetDeviceAuthorizationEndpoint() {
46+
return"https://oauth2.googleapis.com/device/code";
47+
}
48+
49+
@Override
50+
publicDeviceAuthorizationJsonExtractorgetDeviceAuthorizationExtractor() {
51+
returnGoogleDeviceAuthorizationJsonExtractor.instance();
3952
}
4053
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
packagecom.github.scribejava.apis.google;
2+
3+
importcom.github.scribejava.core.extractors.DeviceAuthorizationJsonExtractor;
4+
5+
publicclassGoogleDeviceAuthorizationJsonExtractorextendsDeviceAuthorizationJsonExtractor {
6+
7+
protectedGoogleDeviceAuthorizationJsonExtractor() {
8+
}
9+
10+
privatestaticclassInstanceHolder {
11+
12+
privatestaticfinalGoogleDeviceAuthorizationJsonExtractorINSTANCE
13+
=newGoogleDeviceAuthorizationJsonExtractor();
14+
}
15+
16+
publicstaticGoogleDeviceAuthorizationJsonExtractorinstance() {
17+
returnGoogleDeviceAuthorizationJsonExtractor.InstanceHolder.INSTANCE;
18+
}
19+
20+
@Override
21+
protectedStringgetVerificationUriParamName() {
22+
return"verification_url";
23+
}
24+
25+
}

‎scribejava-apis/src/main/java/com/github/scribejava/apis/microsoftazureactivedirectory/BaseMicrosoftAzureActiveDirectoryApi.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ protected String getAuthorizationBaseUrl() {
3030
returnMSFT_LOGIN_URL +tenant +OAUTH_2 +getEndpointVersionPath() +"/authorize";
3131
}
3232

33-
@Override
34-
publicStringgetDeviceAuthorizationUrl() {
35-
returnMSFT_LOGIN_URL +tenant +OAUTH_2 +getEndpointVersionPath() +"/devicecode";
36-
}
37-
3833
@Override
3934
publicClientAuthenticationgetClientAuthentication() {
4035
returnRequestBodyAuthenticationScheme.instance();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
packagecom.github.scribejava.apis.examples;
2+
3+
importcom.github.scribejava.core.builder.ServiceBuilder;
4+
importcom.github.scribejava.apis.GoogleApi20;
5+
importcom.github.scribejava.core.model.DeviceAuthorization;
6+
importcom.github.scribejava.core.model.OAuth2AccessToken;
7+
importcom.github.scribejava.core.model.OAuthRequest;
8+
importcom.github.scribejava.core.model.Response;
9+
importcom.github.scribejava.core.model.Verb;
10+
importcom.github.scribejava.core.oauth.OAuth20Service;
11+
importjava.io.IOException;
12+
importjava.util.Scanner;
13+
importjava.util.concurrent.ExecutionException;
14+
15+
publicclassGoogle20DeviceAuthorizationGrantExample {
16+
17+
privatestaticfinalStringNETWORK_NAME ="Google";
18+
privatestaticfinalStringPROTECTED_RESOURCE_URL ="https://www.googleapis.com/oauth2/v3/userinfo";
19+
20+
privateGoogle20DeviceAuthorizationGrantExample() {
21+
}
22+
23+
@SuppressWarnings("PMD.SystemPrintln")
24+
publicstaticvoidmain(String...args)throwsIOException,InterruptedException,ExecutionException {
25+
// Replace these with your client id and secret
26+
finalStringclientId ="your client id";
27+
finalStringclientSecret ="your_client_secret";
28+
29+
finalOAuth20Serviceservice =newServiceBuilder(clientId)
30+
.debug()
31+
.apiSecret(clientSecret)
32+
.defaultScope("profile")// replace with desired scope
33+
.build(GoogleApi20.instance());
34+
finalScannerin =newScanner(System.in,"UTF-8");
35+
36+
System.out.println("=== " +NETWORK_NAME +"'s OAuth Workflow ===");
37+
System.out.println();
38+
39+
System.out.println("Requesting a set of verification codes...");
40+
41+
finalDeviceAuthorizationdeviceAuthorization =service.getDeviceAuthorizationCodes();
42+
System.out.println("Got the Device Authorization Codes!");
43+
System.out.println(deviceAuthorization);
44+
45+
System.out.println("Now go and authorize ScribeJava. Visit: " +deviceAuthorization.getVerificationUri()
46+
+" and enter the code: " +deviceAuthorization.getUserCode());
47+
if (deviceAuthorization.getVerificationUriComplete() !=null) {
48+
System.out.println("Or visit " +deviceAuthorization.getVerificationUriComplete());
49+
}
50+
51+
System.out.println("Polling for an Access Token...");
52+
finalOAuth2AccessTokenaccessToken =service.pollAccessTokenDeviceAuthorizationGrant(deviceAuthorization);
53+
54+
System.out.println("Got the Access Token!");
55+
System.out.println("(The raw response looks like this: " +accessToken.getRawResponse() +"')");
56+
57+
// Now let's go and ask for a protected resource!
58+
System.out.println("Now we're going to access a protected resource...");
59+
while (true) {
60+
System.out.println("Paste fieldnames to fetch (leave empty to get profile, 'exit' to stop the example)");
61+
System.out.print(">>");
62+
finalStringquery =in.nextLine();
63+
System.out.println();
64+
finalStringrequestUrl;
65+
if ("exit".equals(query)) {
66+
break;
67+
}elseif (query ==null ||query.isEmpty()) {
68+
requestUrl =PROTECTED_RESOURCE_URL;
69+
}else {
70+
requestUrl =PROTECTED_RESOURCE_URL +"?fields=" +query;
71+
}
72+
finalOAuthRequestrequest =newOAuthRequest(Verb.GET,requestUrl);
73+
service.signRequest(accessToken,request);
74+
System.out.println();
75+
try (Responseresponse =service.execute(request)) {
76+
System.out.println(response.getCode());
77+
System.out.println(response.getBody());
78+
}
79+
System.out.println();
80+
}
81+
}
82+
}

‎scribejava-apis/src/test/java/com/github/scribejava/apis/examples/Google20Example.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ private Google20Example() {
2525
@SuppressWarnings("PMD.SystemPrintln")
2626
publicstaticvoidmain(String...args)throwsIOException,InterruptedException,ExecutionException {
2727
// Replace these with your client id and secret
28-
finalStringclientId ="your client id";
29-
finalStringclientSecret ="your client secret";
28+
finalStringclientId ="your_client_id";
29+
finalStringclientSecret ="your_client_secret";
3030
finalStringsecretState ="secret" +newRandom().nextInt(999_999);
3131
finalOAuth20Serviceservice =newServiceBuilder(clientId)
3232
.apiSecret(clientSecret)

‎scribejava-core/src/main/java/com/github/scribejava/core/builder/api/DefaultApi20.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
packagecom.github.scribejava.core.builder.api;
22

3+
importcom.github.scribejava.core.extractors.DeviceAuthorizationJsonExtractor;
34
importcom.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor;
45
importcom.github.scribejava.core.extractors.TokenExtractor;
56
importcom.github.scribejava.core.httpclient.HttpClient;
@@ -122,7 +123,18 @@ public ClientAuthentication getClientAuthentication() {
122123
returnHttpBasicAuthenticationScheme.instance();
123124
}
124125

125-
publicStringgetDeviceAuthorizationUrl() {
126-
returnnull;
126+
/**
127+
* RFC 8628 OAuth 2.0 Device Authorization Grant
128+
*
129+
* @see <a href="https://tools.ietf.org/html/rfc8628">RFC 8628</a>
130+
* @return the device authorization endpoint
131+
*/
132+
publicStringgetDeviceAuthorizationEndpoint() {
133+
thrownewUnsupportedOperationException(
134+
"This API doesn't support Device Authorization Grant or we have no info about this");
135+
}
136+
137+
publicDeviceAuthorizationJsonExtractorgetDeviceAuthorizationExtractor() {
138+
returnDeviceAuthorizationJsonExtractor.instance();
127139
}
128140
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
packagecom.github.scribejava.core.extractors;
2+
3+
importcom.fasterxml.jackson.databind.JsonNode;
4+
importcom.fasterxml.jackson.databind.ObjectMapper;
5+
importcom.github.scribejava.core.exceptions.OAuthException;
6+
7+
publicabstractclassAbstractJsonExtractor {
8+
9+
protectedstaticfinalObjectMapperOBJECT_MAPPER =newObjectMapper();
10+
11+
protectedstaticJsonNodeextractRequiredParameter(JsonNodeerrorNode,StringparameterName,StringrawResponse)
12+
throwsOAuthException {
13+
finalJsonNodevalue =errorNode.get(parameterName);
14+
15+
if (value ==null) {
16+
thrownewOAuthException("Response body is incorrect. Can't extract a '" +parameterName
17+
+"' from this: '" +rawResponse +"'",null);
18+
}
19+
20+
returnvalue;
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
packagecom.github.scribejava.core.extractors;
2+
3+
importstaticcom.github.scribejava.core.extractors.AbstractJsonExtractor.OBJECT_MAPPER;
4+
importstaticcom.github.scribejava.core.extractors.AbstractJsonExtractor.extractRequiredParameter;
5+
importcom.fasterxml.jackson.databind.JsonNode;
6+
importcom.github.scribejava.core.model.DeviceAuthorization;
7+
importjava.io.IOException;
8+
importcom.github.scribejava.core.model.Response;
9+
10+
publicclassDeviceAuthorizationJsonExtractorextendsAbstractJsonExtractor {
11+
12+
protectedDeviceAuthorizationJsonExtractor() {
13+
}
14+
15+
privatestaticclassInstanceHolder {
16+
17+
privatestaticfinalDeviceAuthorizationJsonExtractorINSTANCE =newDeviceAuthorizationJsonExtractor();
18+
}
19+
20+
publicstaticDeviceAuthorizationJsonExtractorinstance() {
21+
returnInstanceHolder.INSTANCE;
22+
}
23+
24+
publicDeviceAuthorizationextract(Responseresponse)throwsIOException {
25+
26+
finalStringbody =response.getBody();
27+
28+
if (response.getCode() !=200) {
29+
generateError(body);
30+
}
31+
returncreateDeviceAuthorization(body);
32+
}
33+
34+
publicvoidgenerateError(StringrawResponse)throwsIOException {
35+
OAuth2AccessTokenJsonExtractor.instance().generateError(rawResponse);
36+
}
37+
38+
privateDeviceAuthorizationcreateDeviceAuthorization(StringrawResponse)throwsIOException {
39+
40+
finalJsonNoderesponse =OBJECT_MAPPER.readTree(rawResponse);
41+
42+
finalDeviceAuthorizationdeviceAuthorization =newDeviceAuthorization(
43+
extractRequiredParameter(response,"device_code",rawResponse).textValue(),
44+
extractRequiredParameter(response,"user_code",rawResponse).textValue(),
45+
extractRequiredParameter(response,getVerificationUriParamName(),rawResponse).textValue(),
46+
extractRequiredParameter(response,"expires_in",rawResponse).intValue());
47+
48+
finalJsonNodeintervalSeconds =response.get("interval");
49+
if (intervalSeconds !=null) {
50+
deviceAuthorization.setIntervalSeconds(intervalSeconds.asInt(5));
51+
}
52+
53+
finalJsonNodeverificationUriComplete =response.get("verification_uri_complete");
54+
if (verificationUriComplete !=null) {
55+
deviceAuthorization.setVerificationUriComplete(verificationUriComplete.asText());
56+
}
57+
58+
returndeviceAuthorization;
59+
}
60+
61+
protectedStringgetVerificationUriParamName() {
62+
return"verification_uri";
63+
}
64+
}

‎scribejava-core/src/main/java/com/github/scribejava/core/extractors/OAuth2AccessTokenJsonExtractor.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
packagecom.github.scribejava.core.extractors;
22

33
importcom.fasterxml.jackson.databind.JsonNode;
4-
importcom.fasterxml.jackson.databind.ObjectMapper;
54
importjava.io.IOException;
65
importjava.net.URI;
7-
importcom.github.scribejava.core.exceptions.OAuthException;
86
importcom.github.scribejava.core.model.OAuth2AccessToken;
97
importcom.github.scribejava.core.model.OAuth2AccessTokenErrorResponse;
108
importcom.github.scribejava.core.model.OAuthConstants;
@@ -15,9 +13,7 @@
1513
/**
1614
* JSON (default) implementation of {@link TokenExtractor} for OAuth 2.0
1715
*/
18-
publicclassOAuth2AccessTokenJsonExtractorimplementsTokenExtractor<OAuth2AccessToken> {
19-
20-
protectedstaticfinalObjectMapperOBJECT_MAPPER =newObjectMapper();
16+
publicclassOAuth2AccessTokenJsonExtractorextendsAbstractJsonExtractorimplementsTokenExtractor<OAuth2AccessToken> {
2117

2218
protectedOAuth2AccessTokenJsonExtractor() {
2319
}
@@ -92,16 +88,4 @@ protected OAuth2AccessToken createToken(String accessToken, String tokenType, In
9288
StringrefreshToken,Stringscope,JsonNoderesponse,StringrawResponse) {
9389
returnnewOAuth2AccessToken(accessToken,tokenType,expiresIn,refreshToken,scope,rawResponse);
9490
}
95-
96-
publicstaticJsonNodeextractRequiredParameter(JsonNodeerrorNode,StringparameterName,StringrawResponse)
97-
throwsOAuthException {
98-
finalJsonNodevalue =errorNode.get(parameterName);
99-
100-
if (value ==null) {
101-
thrownewOAuthException("Response body is incorrect. Can't extract a '" +parameterName
102-
+"' from this: '" +rawResponse +"'",null);
103-
}
104-
105-
returnvalue;
106-
}
10791
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp