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

Commit7bb59c3

Browse files
author
Štěpán Schejbal
committed
initial support for device flow
1 parenta7b01f6 commit7bb59c3

File tree

6 files changed

+172
-8
lines changed

6 files changed

+172
-8
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ 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+
3338
@Override
3439
publicClientAuthenticationgetClientAuthentication() {
3540
returnRequestBodyAuthenticationScheme.instance();

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,8 @@ public BearerSignature getBearerSignature() {
121121
publicClientAuthenticationgetClientAuthentication() {
122122
returnHttpBasicAuthenticationScheme.instance();
123123
}
124+
125+
publicStringgetDeviceAuthorizationUrl() {
126+
returnnull;
127+
}
124128
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ protected OAuth2AccessToken createToken(String accessToken, String tokenType, In
9393
returnnewOAuth2AccessToken(accessToken,tokenType,expiresIn,refreshToken,scope,rawResponse);
9494
}
9595

96-
protectedstaticJsonNodeextractRequiredParameter(JsonNodeerrorNode,StringparameterName,StringrawResponse)
96+
publicstaticJsonNodeextractRequiredParameter(JsonNodeerrorNode,StringparameterName,StringrawResponse)
9797
throwsOAuthException {
9898
finalJsonNodevalue =errorNode.get(parameterName);
9999

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
packagecom.github.scribejava.core.model;
2+
3+
publicclassDeviceCode {
4+
privateStringdeviceCode;
5+
privateStringuserCode;
6+
privateStringverificationUri;
7+
privateintintervalSeconds;
8+
privatelongexpiresAtMillis;
9+
10+
publicDeviceCode(StringdeviceCode,StringuserCode,StringverificationUri,
11+
intintervalSeconds,intexpiresInSeconds) {
12+
this.deviceCode =deviceCode;
13+
this.userCode =userCode;
14+
this.verificationUri =verificationUri;
15+
this.intervalSeconds =intervalSeconds;
16+
expiresAtMillis =System.currentTimeMillis() + (expiresInSeconds *1000);
17+
}
18+
19+
publicStringgetDeviceCode() {
20+
returndeviceCode;
21+
}
22+
23+
publicStringgetUserCode() {
24+
returnuserCode;
25+
}
26+
27+
publicStringgetVerificationUri() {
28+
returnverificationUri;
29+
}
30+
31+
publicintgetIntervalSeconds() {
32+
returnintervalSeconds;
33+
}
34+
35+
publiclonggetExpiresAtMillis() {
36+
returnexpiresAtMillis;
37+
}
38+
}

‎scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth20Service.java

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
11
packagecom.github.scribejava.core.oauth;
22

3-
importjava.io.IOException;
4-
importjava.io.OutputStream;
5-
importjava.util.concurrent.Future;
3+
importcom.fasterxml.jackson.databind.JsonNode;
4+
importcom.fasterxml.jackson.databind.ObjectMapper;
65
importcom.github.scribejava.core.builder.api.DefaultApi20;
76
importcom.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor;
87
importcom.github.scribejava.core.httpclient.HttpClient;
98
importcom.github.scribejava.core.httpclient.HttpClientConfig;
9+
importcom.github.scribejava.core.model.DeviceCode;
1010
importcom.github.scribejava.core.model.OAuth2AccessToken;
11+
importcom.github.scribejava.core.model.OAuth2AccessTokenErrorResponse;
1112
importcom.github.scribejava.core.model.OAuth2Authorization;
1213
importcom.github.scribejava.core.model.OAuthAsyncRequestCallback;
1314
importcom.github.scribejava.core.model.OAuthConstants;
1415
importcom.github.scribejava.core.model.OAuthRequest;
1516
importcom.github.scribejava.core.model.Response;
1617
importcom.github.scribejava.core.model.Verb;
18+
importcom.github.scribejava.core.oauth2.OAuth2Error;
1719
importcom.github.scribejava.core.pkce.PKCE;
18-
importjava.util.Map;
19-
importjava.util.concurrent.ExecutionException;
2020
importcom.github.scribejava.core.revoke.TokenTypeHint;
21+
importjava.io.IOException;
22+
importjava.io.OutputStream;
2123
importjava.io.UnsupportedEncodingException;
2224
importjava.net.URLDecoder;
25+
importjava.util.Map;
26+
importjava.util.concurrent.ExecutionException;
27+
importjava.util.concurrent.Future;
28+
29+
importstaticcom.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor.extractRequiredParameter;
30+
importstaticcom.github.scribejava.core.oauth2.OAuth2Error.AUTHORIZATION_PENDING;
31+
importstaticcom.github.scribejava.core.oauth2.OAuth2Error.SLOW_DOWN;
32+
importstaticjava.lang.Thread.sleep;
2333

2434
publicclassOAuth20ServiceextendsOAuthService {
35+
protectedstaticfinalObjectMapperOBJECT_MAPPER =newObjectMapper();
2536

2637
privatestaticfinalStringVERSION ="2.0";
2738
privatefinalDefaultApi20api;
@@ -490,4 +501,83 @@ public String getResponseType() {
490501
publicStringgetDefaultScope() {
491502
returndefaultScope;
492503
}
504+
505+
/**
506+
* Requests a device code from a server.
507+
*
508+
* @see <a href="https://tools.ietf.org/html/rfc8628#section-3">rfc8628</a>
509+
* @see <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code">
510+
* azure v2-oauth2-device-code</a>
511+
*/
512+
publicDeviceCodegetDeviceCode()throwsInterruptedException,ExecutionException,IOException {
513+
finalOAuthRequestrequest =newOAuthRequest(Verb.POST,api.getDeviceAuthorizationUrl());
514+
request.addBodyParameter(OAuthConstants.CLIENT_ID,getApiKey());
515+
request.addBodyParameter(OAuthConstants.SCOPE,getDefaultScope());
516+
try (Responseresponse =execute(request)) {
517+
finalStringbody =response.getBody();
518+
if (response.getCode() ==200) {
519+
finalJsonNoden =OBJECT_MAPPER.readTree(body);
520+
returnnewDeviceCode(
521+
extractRequiredParameter(n,"device_code",body).textValue(),
522+
extractRequiredParameter(n,"user_code",body).textValue(),
523+
extractRequiredParameter(n,"verification_uri",body).textValue(),
524+
n.path("interval").asInt(5),
525+
extractRequiredParameter(n,"expires_in",body).intValue());
526+
}else {
527+
OAuth2AccessTokenJsonExtractor.instance().generateError(body);
528+
thrownewIllegalStateException();// generateError() always throws an exception
529+
}
530+
}
531+
}
532+
533+
/**
534+
* Attempts to get a token from a server.
535+
* Function {@link #pollDeviceAccessToken(DeviceCode)} is usually used instead of this.
536+
*
537+
* @return token
538+
* @throws OAuth2AccessTokenErrorResponse
539+
* If {@link OAuth2AccessTokenErrorResponse#getError()} is
540+
* {@link OAuth2Error#AUTHORIZATION_PENDING} or {@link OAuth2Error#SLOW_DOWN},
541+
* another attempt should be made after a while.
542+
*
543+
* @see #getDeviceCode()
544+
*/
545+
publicOAuth2AccessTokengetAccessTokenDeviceCodeGrant(DeviceCodedeviceCode)
546+
throwsIOException,InterruptedException,ExecutionException {
547+
finalOAuthRequestrequest =newOAuthRequest(Verb.POST,api.getAccessTokenEndpoint());
548+
request.addParameter(OAuthConstants.GRANT_TYPE,"urn:ietf:params:oauth:grant-type:device_code");
549+
request.addBodyParameter(OAuthConstants.CLIENT_ID,getApiKey());
550+
request.addParameter("device_code",deviceCode.getDeviceCode());
551+
try (Responseresponse =execute(request)) {
552+
returnapi.getAccessTokenExtractor().extract(response);
553+
}
554+
}
555+
556+
/**
557+
* Periodically tries to get a token from a server (waiting for the user to give consent).
558+
*
559+
* @return token
560+
* @throws OAuth2AccessTokenErrorResponse
561+
* Indicates OAuth error.
562+
*
563+
* @see #getDeviceCode()
564+
*/
565+
publicOAuth2AccessTokenpollDeviceAccessToken(DeviceCodedeviceCode)
566+
throwsInterruptedException,ExecutionException,IOException {
567+
longintervalMillis =deviceCode.getIntervalSeconds() *1000;
568+
while (true) {
569+
try {
570+
returngetAccessTokenDeviceCodeGrant(deviceCode);
571+
}catch (OAuth2AccessTokenErrorResponsee) {
572+
if (e.getError() !=AUTHORIZATION_PENDING) {
573+
if (e.getError() ==SLOW_DOWN) {
574+
intervalMillis +=5000;
575+
}else {
576+
throwe;
577+
}
578+
}
579+
}
580+
sleep(intervalMillis);
581+
}
582+
}
493583
}

‎scribejava-core/src/main/java/com/github/scribejava/core/oauth2/OAuth2Error.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
packagecom.github.scribejava.core.oauth2;
22

3+
importjava.util.EnumSet;
4+
importjava.util.Set;
5+
6+
importstaticjava.util.Collections.unmodifiableSet;
7+
38
publicenumOAuth2Error {
49
/**
510
* @see <a href="https://tools.ietf.org/html/rfc6749#section-4.1.2.1">RFC 6749, 4.1.2.1 Error Response</a>
@@ -67,7 +72,29 @@ public enum OAuth2Error {
6772
* @see <a href="https://tools.ietf.org/html/rfc7009#section-4.1">RFC 7009, 4.1. OAuth Extensions Error
6873
* Registration</a>
6974
*/
70-
UNSUPPORTED_TOKEN_TYPE("unsupported_token_type");
75+
UNSUPPORTED_TOKEN_TYPE("unsupported_token_type"),
76+
77+
/**
78+
* @see <a href="https://tools.ietf.org/html/rfc8628#section-3.5">rfc8628#section-3.5</a>
79+
*/
80+
AUTHORIZATION_PENDING("authorization_pending"),
81+
82+
/**
83+
* @see <a href="https://tools.ietf.org/html/rfc8628#section-3.5">rfc8628#section-3.5</a>
84+
*/
85+
SLOW_DOWN("slow_down"),
86+
87+
/**
88+
* @see <a href="https://tools.ietf.org/html/rfc8628#section-3.5">rfc8628#section-3.5</a>
89+
*/
90+
EXPIRED_TOKEN("expired_token"),
91+
;
92+
93+
/**
94+
* Unlike {@link #values()} which creates a new array every time, this always
95+
* returns the same immutable object.
96+
*/
97+
publicstaticfinalSet<OAuth2Error>VALUES =unmodifiableSet(EnumSet.allOf(OAuth2Error.class));
7198

7299
privatefinalStringerrorString;
73100

@@ -76,7 +103,7 @@ public enum OAuth2Error {
76103
}
77104

78105
publicstaticOAuth2ErrorparseFrom(StringerrorString) {
79-
for (OAuth2Errorerror :OAuth2Error.values()) {
106+
for (OAuth2Errorerror :VALUES) {
80107
if (error.errorString.equals(errorString)) {
81108
returnerror;
82109
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp