Skip to content

Commit 49228d2

Browse files
committed
updates to oauth
1 parent 0f9720c commit 49228d2

File tree

4 files changed

+296
-3
lines changed

4 files changed

+296
-3
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{{>licenseInfo}}
2+
3+
{{#hasOAuthMethods}}
4+
package {{invokerPackage}}.auth;
5+
6+
import okhttp3.OkHttpClient;
7+
import okhttp3.MediaType;
8+
import okhttp3.Request;
9+
import okhttp3.RequestBody;
10+
import okhttp3.Response;
11+
12+
import org.apache.oltu.oauth2.client.HttpClient;
13+
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
14+
import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
15+
import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory;
16+
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
17+
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
18+
19+
import java.io.IOException;
20+
import java.util.Map;
21+
import java.util.Map.Entry;
22+
23+
public class OAuthOkHttpClient implements HttpClient {
24+
private OkHttpClient client;
25+
26+
public OAuthOkHttpClient() {
27+
this.client = new OkHttpClient();
28+
}
29+
30+
public OAuthOkHttpClient(OkHttpClient client) {
31+
this.client = client;
32+
}
33+
34+
@Override
35+
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
36+
String requestMethod, Class<T> responseClass)
37+
throws OAuthSystemException, OAuthProblemException {
38+
39+
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
40+
Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri());
41+
42+
headers = request.getHeaders();
43+
44+
if(headers != null) {
45+
for (Entry<String, String> entry : headers.entrySet()) {
46+
if (entry.getKey().equalsIgnoreCase("Content-Type")) {
47+
mediaType = MediaType.parse(entry.getValue());
48+
} else {
49+
requestBuilder.addHeader(entry.getKey(), entry.getValue());
50+
}
51+
}
52+
}
53+
54+
RequestBody body = request.getBody() != null ? RequestBody.create(request.getBody(), mediaType) : null;
55+
requestBuilder.method(requestMethod, body);
56+
57+
try {
58+
Response response = client.newCall(requestBuilder.build()).execute();
59+
return OAuthClientResponseFactory.createCustomResponse(
60+
response.body().string(),
61+
response.body().contentType().toString(),
62+
response.code(),
63+
response.headers().toMultimap(),
64+
responseClass);
65+
} catch (IOException e) {
66+
throw new OAuthSystemException(e);
67+
}
68+
}
69+
70+
@Override
71+
public void shutdown() {
72+
// Nothing to do here
73+
}
74+
}
75+
{{/hasOAuthMethods}}
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
{{>licenseInfo}}
2+
3+
{{#hasOAuthMethods}}
4+
package {{invokerPackage}}.auth;
5+
6+
import {{invokerPackage}}.ApiException;
7+
import {{invokerPackage}}.Pair;
8+
9+
import okhttp3.Interceptor;
10+
import okhttp3.OkHttpClient;
11+
import okhttp3.Request;
12+
import okhttp3.Response;
13+
14+
import org.apache.oltu.oauth2.client.OAuthClient;
15+
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
16+
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
17+
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
18+
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
19+
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
20+
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
21+
import org.apache.oltu.oauth2.common.message.types.GrantType;
22+
23+
import java.io.IOException;
24+
import java.net.HttpURLConnection;
25+
import java.net.URI;
26+
import java.util.Map;
27+
import java.util.List;
28+
29+
public class RetryingOAuth extends OAuth implements Interceptor {
30+
private OAuthClient oAuthClient;
31+
32+
private TokenRequestBuilder tokenRequestBuilder;
33+
34+
/**
35+
* @param client An OkHttp client
36+
* @param tokenRequestBuilder A token request builder
37+
*/
38+
public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) {
39+
this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client));
40+
this.tokenRequestBuilder = tokenRequestBuilder;
41+
}
42+
43+
/**
44+
* @param tokenRequestBuilder A token request builder
45+
*/
46+
public RetryingOAuth(TokenRequestBuilder tokenRequestBuilder) {
47+
this(new OkHttpClient(), tokenRequestBuilder);
48+
}
49+
50+
/**
51+
* @param tokenUrl The token URL to be used for this OAuth2 flow.
52+
* Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode".
53+
* The value must be an absolute URL.
54+
* @param clientId The OAuth2 client ID for the "clientCredentials" flow.
55+
* @param flow OAuth flow.
56+
* @param clientSecret The OAuth2 client secret for the "clientCredentials" flow.
57+
* @param parameters A map of string.
58+
*/
59+
public RetryingOAuth(
60+
String tokenUrl,
61+
String clientId,
62+
OAuthFlow flow,
63+
String clientSecret,
64+
Map<String, String> parameters
65+
) {
66+
this(OAuthClientRequest.tokenLocation(tokenUrl)
67+
.setClientId(clientId)
68+
.setClientSecret(clientSecret));
69+
setFlow(flow);
70+
if (parameters != null) {
71+
for (Map.Entry<String, String> entry : parameters.entrySet()) {
72+
tokenRequestBuilder.setParameter(entry.getKey(), entry.getValue());
73+
}
74+
}
75+
}
76+
77+
/**
78+
* Set the OAuth flow
79+
*
80+
* @param flow The OAuth flow.
81+
*/
82+
public void setFlow(OAuthFlow flow) {
83+
switch(flow) {
84+
case ACCESS_CODE:
85+
tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE);
86+
break;
87+
case IMPLICIT:
88+
tokenRequestBuilder.setGrantType(GrantType.IMPLICIT);
89+
break;
90+
case PASSWORD:
91+
tokenRequestBuilder.setGrantType(GrantType.PASSWORD);
92+
break;
93+
case APPLICATION:
94+
tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS);
95+
break;
96+
default:
97+
break;
98+
}
99+
}
100+
101+
@Override
102+
public Response intercept(Chain chain) throws IOException {
103+
return retryingIntercept(chain, true);
104+
}
105+
106+
private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException {
107+
Request request = chain.request();
108+
109+
// If the request already has an authorization (e.g. Basic auth), proceed with the request as is
110+
if (request.header("Authorization") != null) {
111+
return chain.proceed(request);
112+
}
113+
114+
// Get the token if it has not yet been acquired
115+
if (getAccessToken() == null) {
116+
updateAccessToken(null);
117+
}
118+
119+
OAuthClientRequest oAuthRequest;
120+
if (getAccessToken() != null) {
121+
// Build the request
122+
Request.Builder requestBuilder = request.newBuilder();
123+
124+
String requestAccessToken = getAccessToken();
125+
try {
126+
oAuthRequest =
127+
new OAuthBearerClientRequest(request.url().toString()).
128+
setAccessToken(requestAccessToken).
129+
buildHeaderMessage();
130+
} catch (OAuthSystemException e) {
131+
throw new IOException(e);
132+
}
133+
134+
Map<String, String> headers = oAuthRequest.getHeaders();
135+
for (Map.Entry<String, String> entry : headers.entrySet()) {
136+
requestBuilder.addHeader(entry.getKey(), entry.getValue());
137+
}
138+
requestBuilder.url(oAuthRequest.getLocationUri());
139+
140+
// Execute the request
141+
Response response = chain.proceed(requestBuilder.build());
142+
143+
// 401/403 response codes most likely indicate an expired access token, unless it happens two times in a row
144+
if (
145+
response != null &&
146+
( response.code() == HttpURLConnection.HTTP_UNAUTHORIZED ||
147+
response.code() == HttpURLConnection.HTTP_FORBIDDEN ) &&
148+
updateTokenAndRetryOnAuthorizationFailure
149+
) {
150+
try {
151+
if (updateAccessToken(requestAccessToken)) {
152+
response.body().close();
153+
return retryingIntercept(chain, false);
154+
}
155+
} catch (Exception e) {
156+
response.body().close();
157+
throw e;
158+
}
159+
}
160+
return response;
161+
}
162+
else {
163+
return chain.proceed(chain.request());
164+
}
165+
}
166+
167+
/**
168+
* Returns true if the access token has been updated
169+
*
170+
* @param requestAccessToken the request access token
171+
* @return True if the update is successful
172+
* @throws java.io.IOException If fail to update the access token
173+
*/
174+
public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
175+
if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
176+
try {
177+
OAuthClientRequest req = tokenRequestBuilder.buildBodyMessage();
178+
req.setHeader("Authorization", "Basic ZGURuOTM=");
179+
OAuthJSONAccessTokenResponse accessTokenResponse = oAuthClient.accessToken(req);
180+
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
181+
setAccessToken(accessTokenResponse.getAccessToken());
182+
}
183+
} catch (OAuthSystemException | OAuthProblemException e) {
184+
throw new IOException(e);
185+
}
186+
}
187+
return getAccessToken() == null || !getAccessToken().equals(requestAccessToken);
188+
}
189+
190+
/**
191+
* Gets the token request builder
192+
*
193+
* @return A token request builder
194+
*/
195+
public TokenRequestBuilder getTokenRequestBuilder() {
196+
return tokenRequestBuilder;
197+
}
198+
199+
/**
200+
* Sets the token request builder
201+
*
202+
* @param tokenRequestBuilder Token request builder
203+
*/
204+
public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
205+
this.tokenRequestBuilder = tokenRequestBuilder;
206+
}
207+
208+
// Applying authorization to parameters is performed in the retryingIntercept method
209+
@Override
210+
public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams, Map<String, String> cookieParams,
211+
String payload, String method, URI uri) throws ApiException {
212+
// No implementation necessary
213+
}
214+
}
215+
{{/hasOAuthMethods}}

src/main/java/com/bandwidth/sdk/auth/OAuthOkHttpClient.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map
4646
String requestMethod, Class<T> responseClass)
4747
throws OAuthSystemException, OAuthProblemException {
4848

49-
MediaType mediaType = MediaType.parse("application/json");
49+
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
5050
Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri());
51+
52+
headers = request.getHeaders();
5153

5254
if(headers != null) {
5355
for (Entry<String, String> entry : headers.entrySet()) {

src/main/java/com/bandwidth/sdk/auth/RetryingOAuth.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,9 @@ private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAut
184184
public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
185185
if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
186186
try {
187-
OAuthJSONAccessTokenResponse accessTokenResponse =
188-
oAuthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
187+
OAuthClientRequest req = tokenRequestBuilder.buildBodyMessage();
188+
req.setHeader("Authorization", "Basic ZGURuOTM=");
189+
OAuthJSONAccessTokenResponse accessTokenResponse = oAuthClient.accessToken(req);
189190
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
190191
setAccessToken(accessTokenResponse.getAccessToken());
191192
}

0 commit comments

Comments
 (0)