[okhttp-gson] Add support for OAuth access token retry (#1058)

* Add support for access token retry in okhttp-gson lib

* Update expected number of generated files in test

* Update samples

* Update security samples

* Fix default user-agent and update samples
This commit is contained in:
Kiran-Sivakumar
2018-09-20 04:29:59 -07:00
committed by William Cheng
parent 1b2f3fbfb6
commit 0e045bee1b
29 changed files with 1166 additions and 73 deletions

View File

@@ -288,6 +288,8 @@ public class JavaClientCodegen extends AbstractJavaCodegen
supportingFiles.add(new SupportingFile("ProgressRequestBody.mustache", invokerFolder, "ProgressRequestBody.java"));
supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java"));
supportingFiles.add(new SupportingFile("GzipRequestInterceptor.mustache", invokerFolder, "GzipRequestInterceptor.java"));
supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));
supportingFiles.add(new SupportingFile("auth/RetryingOAuth.mustache", authFolder, "RetryingOAuth.java"));
additionalProperties.put("gson", "true");
} else if (usesAnyRetrofitLibrary()) {
supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java"));

View File

@@ -19,6 +19,9 @@ import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.format.DateTimeFormatter;
{{/threetenbp}}
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
@@ -50,6 +53,7 @@ import {{invokerPackage}}.auth.Authentication;
import {{invokerPackage}}.auth.HttpBasicAuth;
import {{invokerPackage}}.auth.ApiKeyAuth;
import {{invokerPackage}}.auth.OAuth;
import {{invokerPackage}}.auth.RetryingOAuth;
public class ApiClient {
@@ -78,6 +82,38 @@ public class ApiClient {
* Constructor for ApiClient
*/
public ApiClient() {
init();
// Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}
authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}}
authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
{{#authMethods}}{{#isOAuth}}
/*
* Constructor for ApiClient to support access token retry on 401/403
*/
public ApiClient(
String clientId,
String clientSecret,
Map<String, String> parameters
) {
init();
RetryingOAuth retryingOAuth = new RetryingOAuth("{{tokenUrl}}", clientId, GrantType.valueOf("{{flow}}"), clientSecret, parameters);
authentications.put(
"{{name}}",
retryingOAuth
);
httpClient.interceptors().add(retryingOAuth);
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
{{/isOAuth}}{{/authMethods}}
private void init() {
httpClient = new OkHttpClient();
{{#useGzipFeature}}
@@ -92,13 +128,7 @@ public class ApiClient {
// Set default User-Agent.
setUserAgent("{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{artifactVersion}}}/java{{/httpUserAgent}}");
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();{{#authMethods}}{{#isBasic}}
authentications.put("{{name}}", new HttpBasicAuth());{{/isBasic}}{{#isApiKey}}
authentications.put("{{name}}", new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{keyParamName}}"));{{/isApiKey}}{{#isOAuth}}
authentications.put("{{name}}", new OAuth());{{/isOAuth}}{{/authMethods}}
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
authentications = new HashMap<String, Authentication>();
}
/**
@@ -502,6 +532,20 @@ public class ApiClient {
return this;
}
/**
* Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one)
* @return Token request builder
*/
public TokenRequestBuilder getTokenEndPoint() {
for (Authentication apiAuth : authentications.values()) {
if (apiAuth instanceof RetryingOAuth) {
RetryingOAuth retryingOAuth = (RetryingOAuth) apiAuth;
return retryingOAuth.getTokenRequestBuilder();
}
}
return null;
}
/**
* Format the given parameter object into string.
*

View File

@@ -0,0 +1,68 @@
package {{invokerPackage}}.auth;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import org.apache.oltu.oauth2.client.HttpClient;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
public class OAuthOkHttpClient implements HttpClient {
private OkHttpClient client;
public OAuthOkHttpClient() {
this.client = new OkHttpClient();
}
public OAuthOkHttpClient(OkHttpClient client) {
this.client = client;
}
@Override
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
MediaType mediaType = MediaType.parse("application/json");
Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri());
if(headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().equalsIgnoreCase("Content-Type")) {
mediaType = MediaType.parse(entry.getValue());
} else {
requestBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
}
RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null;
requestBuilder.method(requestMethod, body);
try {
Response response = client.newCall(requestBuilder.build()).execute();
return OAuthClientResponseFactory.createCustomResponse(
response.body().string(),
response.body().contentType().toString(),
response.code(),
responseClass);
} catch (IOException e) {
throw new OAuthSystemException(e);
}
}
@Override
public void shutdown() {
// Nothing to do here
}
}

View File

@@ -0,0 +1,147 @@
package {{invokerPackage}}.auth;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Map;
public class RetryingOAuth extends OAuth implements Interceptor {
private OAuthClient oAuthClient;
private TokenRequestBuilder tokenRequestBuilder;
public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) {
this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client));
this.tokenRequestBuilder = tokenRequestBuilder;
}
public RetryingOAuth(TokenRequestBuilder tokenRequestBuilder) {
this(new OkHttpClient(), tokenRequestBuilder);
}
public RetryingOAuth(
String tokenUrl,
String clientId,
GrantType grantType,
String clientSecret,
Map<String, String> parameters
) {
this(OAuthClientRequest.tokenLocation(tokenUrl)
.setClientId(clientId)
.setGrantType(grantType)
.setClientSecret(clientSecret));
if (parameters != null) {
for (String paramName : parameters.keySet()) {
tokenRequestBuilder.setParameter(paramName, parameters.get(paramName));
}
}
}
@Override
public Response intercept(Chain chain) throws IOException {
return retryingIntercept(chain, true);
}
private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException {
Request request = chain.request();
// If the request already has an authorization (e.g. Basic auth), proceed with the request as is
if (request.header("Authorization") != null) {
return chain.proceed(request);
}
// Get the token if it has not yet been acquired
if (getAccessToken() == null) {
updateAccessToken(null);
}
OAuthClientRequest oAuthRequest;
if (getAccessToken() != null) {
// Build the request
Request.Builder requestBuilder = request.newBuilder();
String requestAccessToken = getAccessToken();
try {
oAuthRequest =
new OAuthBearerClientRequest(request.urlString()).
setAccessToken(requestAccessToken).
buildHeaderMessage();
} catch (OAuthSystemException e) {
throw new IOException(e);
}
Map<String, String> headers = oAuthRequest.getHeaders();
for (String headerName : headers.keySet()) {
requestBuilder.addHeader(headerName, headers.get(headerName));
}
requestBuilder.url(oAuthRequest.getLocationUri());
// Execute the request
Response response = chain.proceed(requestBuilder.build());
// 401/403 response codes most likely indicate an expired access token, unless it happens two times in a row
if (
response != null &&
( response.code() == HttpURLConnection.HTTP_UNAUTHORIZED ||
response.code() == HttpURLConnection.HTTP_FORBIDDEN ) &&
updateTokenAndRetryOnAuthorizationFailure
) {
try {
if (updateAccessToken(requestAccessToken)) {
response.body().close();
return retryingIntercept(chain, false);
}
} catch (Exception e) {
response.body().close();
throw e;
}
}
return response;
}
else {
return chain.proceed(chain.request());
}
}
/*
* Returns true if the access token has been updated
*/
public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
try {
OAuthJSONAccessTokenResponse accessTokenResponse =
oAuthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
setAccessToken(accessTokenResponse.getAccessToken());
return !getAccessToken().equals(requestAccessToken);
}
} catch (OAuthSystemException | OAuthProblemException e) {
throw new IOException(e);
}
}
return false;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
this.tokenRequestBuilder = tokenRequestBuilder;
}
}

View File

@@ -123,6 +123,7 @@ dependencies {
compile 'com.squareup.okhttp:logging-interceptor:2.7.5'
compile 'com.google.code.gson:gson:2.8.1'
compile 'io.gsonfire:gson-fire:1.8.0'
compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1'
{{#joda}}
compile 'joda-time:joda-time:2.9.9'
{{/joda}}

View File

@@ -213,6 +213,11 @@
<artifactId>gson-fire</artifactId>
<version>${gson-fire-version}</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>1.0.1</version>
</dependency>
{{#joda}}
<dependency>
<groupId>joda-time</groupId>

View File

@@ -252,7 +252,7 @@ public class JavaClientCodegenTest {
generator.opts(clientOptInput).generate();
Map<String, String> generatedFiles = generator.getFiles();
Assert.assertEquals(generatedFiles.size(), 35);
Assert.assertEquals(generatedFiles.size(), 37);
ensureContainsFile(generatedFiles, output, ".gitignore");
ensureContainsFile(generatedFiles, output, ".openapi-generator-ignore");
ensureContainsFile(generatedFiles, output, ".openapi-generator/VERSION");

View File

@@ -1 +1 @@
3.2.3-SNAPSHOT
3.3.0-SNAPSHOT

View File

@@ -99,6 +99,7 @@ dependencies {
compile 'com.squareup.okhttp:logging-interceptor:2.7.5'
compile 'com.google.code.gson:gson:2.8.1'
compile 'io.gsonfire:gson-fire:1.8.0'
compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1'
compile 'org.threeten:threetenbp:1.3.5'
testCompile 'junit:junit:4.12'
}

View File

@@ -212,6 +212,11 @@
<groupId>io.gsonfire</groupId>
<artifactId>gson-fire</artifactId>
<version>${gson-fire-version}</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.threeten</groupId>

View File

@@ -23,6 +23,9 @@ import org.threeten.bp.LocalDate;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.format.DateTimeFormatter;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
@@ -49,6 +52,7 @@ import org.openapitools.client.auth.Authentication;
import org.openapitools.client.auth.HttpBasicAuth;
import org.openapitools.client.auth.ApiKeyAuth;
import org.openapitools.client.auth.OAuth;
import org.openapitools.client.auth.RetryingOAuth;
public class ApiClient {
@@ -77,6 +81,37 @@ public class ApiClient {
* Constructor for ApiClient
*/
public ApiClient() {
init();
// Setup authentications (key: authentication name, value: authentication).
authentications.put("api_key", new ApiKeyAuth("header", "api_key */ &#39; &quot; &#x3D;end -- \r\n \n \r"));
authentications.put("petstore_auth", new OAuth());
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
/*
* Constructor for ApiClient to support access token retry on 401/403
*/
public ApiClient(
String clientId,
String clientSecret,
Map<String, String> parameters
) {
init();
RetryingOAuth retryingOAuth = new RetryingOAuth("", clientId, GrantType.valueOf("implicit"), clientSecret, parameters);
authentications.put(
"petstore_auth",
retryingOAuth
);
httpClient.interceptors().add(retryingOAuth);
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
private void init() {
httpClient = new OkHttpClient();
@@ -87,12 +122,7 @@ public class ApiClient {
// Set default User-Agent.
setUserAgent("OpenAPI-Generator/1.0.0/java");
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();
authentications.put("api_key", new ApiKeyAuth("header", "api_key */ &#39; &quot; &#x3D;end -- \r\n \n \r"));
authentications.put("petstore_auth", new OAuth());
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
/**
@@ -482,6 +512,20 @@ public class ApiClient {
return this;
}
/**
* Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one)
* @return Token request builder
*/
public TokenRequestBuilder getTokenEndPoint() {
for (Authentication apiAuth : authentications.values()) {
if (apiAuth instanceof RetryingOAuth) {
RetryingOAuth retryingOAuth = (RetryingOAuth) apiAuth;
return retryingOAuth.getTokenRequestBuilder();
}
}
return null;
}
/**
* Format the given parameter object into string.
*
@@ -497,7 +541,7 @@ public class ApiClient {
return jsonStr.substring(1, jsonStr.length() - 1);
} else if (param instanceof Collection) {
StringBuilder b = new StringBuilder();
for (Object o : (Collection)param) {
for (Object o : (Collection) param) {
if (b.length() > 0) {
b.append(",");
}
@@ -522,7 +566,9 @@ public class ApiClient {
List<Pair> params = new ArrayList<Pair>();
// preconditions
if (name == null || name.isEmpty() || value == null || value instanceof Collection) return params;
if (name == null || name.isEmpty() || value == null || value instanceof Collection) {
return params;
}
params.add(new Pair(name, parameterToString(value)));
return params;
@@ -567,7 +613,7 @@ public class ApiClient {
delimiter = escapeString("|");
}
StringBuilder sb = new StringBuilder() ;
StringBuilder sb = new StringBuilder();
for (Object item : value) {
sb.append(delimiter);
sb.append(escapeString(parameterToString(item)));
@@ -637,7 +683,7 @@ public class ApiClient {
*/
public String selectHeaderContentType(String[] contentTypes) {
if (contentTypes.length == 0 || contentTypes[0].equals("*/*")) {
return "application/json";
return "application/json";
}
for (String contentType : contentTypes) {
if (isJsonMime(contentType)) {
@@ -961,7 +1007,7 @@ public class ApiClient {
* @param formParams The form parameters
* @param authNames The authentications to apply
* @param progressRequestListener Progress request listener
* @return The HTTP request
* @return The HTTP request
* @throws ApiException If fail to serialize the request body object
*/
public Request buildRequest(String path, String method, List<Pair> queryParams, List<Pair> collectionQueryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String[] authNames, ProgressRequestBody.ProgressRequestListener progressRequestListener) throws ApiException {
@@ -1078,13 +1124,15 @@ public class ApiClient {
* Update query and header parameters based on authentication settings.
*
* @param authNames The authentications to apply
* @param queryParams List of query parameters
* @param headerParams Map of header parameters
* @param queryParams List of query parameters
* @param headerParams Map of header parameters
*/
public void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams) {
for (String authName : authNames) {
Authentication auth = authentications.get(authName);
if (auth == null) throw new RuntimeException("Authentication undefined: " + authName);
if (auth == null) {
throw new RuntimeException("Authentication undefined: " + authName);
}
auth.applyToParams(queryParams, headerParams);
}
}
@@ -1096,7 +1144,7 @@ public class ApiClient {
* @return RequestBody
*/
public RequestBody buildRequestBodyFormEncoding(Map<String, Object> formParams) {
FormEncodingBuilder formBuilder = new FormEncodingBuilder();
FormEncodingBuilder formBuilder = new FormEncodingBuilder();
for (Entry<String, Object> param : formParams.entrySet()) {
formBuilder.add(param.getKey(), parameterToString(param.getValue()));
}
@@ -1159,10 +1207,12 @@ public class ApiClient {
public X509Certificate[] getAcceptedIssuers() { return null; }
};
SSLContext sslContext = SSLContext.getInstance("TLS");
trustManagers = new TrustManager[]{ trustAll };
trustManagers = new TrustManager[] {trustAll};
hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) { return true; }
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
} else if (sslCaCert != null) {
char[] password = null; // Any password will work.

View File

@@ -27,7 +27,8 @@ import java.io.IOException;
* Taken from https://github.com/square/okhttp/issues/350
*/
class GzipRequestInterceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
return chain.proceed(originalRequest);
@@ -63,19 +64,22 @@ class GzipRequestInterceptor implements Interceptor {
private RequestBody gzip(final RequestBody body) {
return new RequestBody() {
@Override public MediaType contentType() {
@Override
public MediaType contentType() {
return body.contentType();
}
@Override public long contentLength() {
@Override
public long contentLength() {
return -1; // We don't know the compressed length in advance!
}
@Override public void writeTo(BufferedSink sink) throws IOException {
@Override
public void writeTo(BufferedSink sink) throws IOException {
BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
body.writeTo(gzipSink);
gzipSink.close();
}
};
}
}
}

View File

@@ -1,6 +1,6 @@
/*
* OpenAPI Petstore *_/ ' \" =end -- \\r\\n \\n \\r
* This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end --
* This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end --
*
* OpenAPI spec version: 1.0.0 *_/ ' \" =end -- \\r\\n \\n \\r
* Contact: something@something.abc *_/ ' \" =end -- \\r\\n \\n \\r
@@ -15,19 +15,21 @@ package org.openapitools.client;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.bind.util.ISO8601Utils;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.google.gson.JsonElement;
import io.gsonfire.GsonFireBuilder;
import okio.ByteString;
import org.openapitools.client.model.*;
import io.gsonfire.TypeSelector;
import org.threeten.bp.LocalDate;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.format.DateTimeFormatter;
import org.openapitools.client.model.*;
import okio.ByteString;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Type;
@@ -37,6 +39,7 @@ import java.text.ParsePosition;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;
public class JSON {
private Gson gson;
@@ -49,7 +52,6 @@ public class JSON {
public static GsonBuilder createGson() {
GsonFireBuilder fireBuilder = new GsonFireBuilder()
;
GsonBuilder builder = fireBuilder.createGsonBuilder();
return builder;
@@ -57,7 +59,7 @@ public class JSON {
private static String getDiscriminatorValue(JsonElement readElement, String discriminatorField) {
JsonElement element = readElement.getAsJsonObject().get(discriminatorField);
if(null == element) {
if (null == element) {
throw new IllegalArgumentException("missing discriminator field: <" + discriminatorField + ">");
}
return element.getAsString();
@@ -65,7 +67,7 @@ public class JSON {
private static Class getClassByDiscriminator(Map classByDiscriminatorValue, String discriminatorValue) {
Class clazz = (Class) classByDiscriminatorValue.get(discriminatorValue.toUpperCase(Locale.ROOT));
if(null == clazz) {
if (null == clazz) {
throw new IllegalArgumentException("cannot determine model class of name: <" + discriminatorValue + ">");
}
return clazz;
@@ -138,9 +140,11 @@ public class JSON {
} catch (JsonParseException e) {
// Fallback processing when failed to parse JSON form response body:
// return the response body string directly for the String return type;
if (returnType.equals(String.class))
if (returnType.equals(String.class)) {
return (T) body;
else throw (e);
} else {
throw (e);
}
}
}
@@ -276,8 +280,7 @@ public class JSON {
private DateFormat dateFormat;
public SqlDateTypeAdapter() {
}
public SqlDateTypeAdapter() {}
public SqlDateTypeAdapter(DateFormat dateFormat) {
this.dateFormat = dateFormat;
@@ -330,8 +333,7 @@ public class JSON {
private DateFormat dateFormat;
public DateTypeAdapter() {
}
public DateTypeAdapter() {}
public DateTypeAdapter(DateFormat dateFormat) {
this.dateFormat = dateFormat;

View File

@@ -24,13 +24,17 @@ public class Pair {
}
private void setName(String name) {
if (!isValidString(name)) return;
if (!isValidString(name)) {
return;
}
this.name = name;
}
private void setValue(String value) {
if (!isValidString(value)) return;
if (!isValidString(value)) {
return;
}
this.value = value;
}
@@ -44,8 +48,13 @@ public class Pair {
}
private boolean isValidString(String arg) {
if (arg == null) return false;
if (arg.trim().isEmpty()) return false;
if (arg == null) {
return false;
}
if (arg.trim().isEmpty()) {
return false;
}
return true;
}

View File

@@ -24,8 +24,12 @@ public class StringUtil {
*/
public static boolean containsIgnoreCase(String[] array, String value) {
for (String str : array) {
if (value == null && str == null) return true;
if (value != null && value.equalsIgnoreCase(str)) return true;
if (value == null && str == null) {
return true;
}
if (value != null && value.equalsIgnoreCase(str)) {
return true;
}
}
return false;
}
@@ -43,7 +47,9 @@ public class StringUtil {
*/
public static String join(String[] array, String separator) {
int len = array.length;
if (len == 0) return "";
if (len == 0) {
return "";
}
StringBuilder out = new StringBuilder();
out.append(array[0]);

View File

@@ -70,16 +70,15 @@ public class FakeApi {
List<Pair> localVarQueryParams = new ArrayList<Pair>();
List<Pair> localVarCollectionQueryParams = new ArrayList<Pair>();
Map<String, String> localVarHeaderParams = new HashMap<String, String>();
Map<String, Object> localVarFormParams = new HashMap<String, Object>();
final String[] localVarAccepts = {
};
final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
if (localVarAccept != null) localVarHeaderParams.put("Accept", localVarAccept);
if (localVarAccept != null) {
localVarHeaderParams.put("Accept", localVarAccept);
}
final String[] localVarContentTypes = {
"application/json", "*_/ ' =end -- "
@@ -87,7 +86,7 @@ public class FakeApi {
final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
localVarHeaderParams.put("Content-Type", localVarContentType);
if(progressListener != null) {
if (progressListener != null) {
apiClient.getHttpClient().networkInterceptors().add(new com.squareup.okhttp.Interceptor() {
@Override
public com.squareup.okhttp.Response intercept(com.squareup.okhttp.Interceptor.Chain chain) throws IOException {

View File

@@ -0,0 +1,68 @@
package org.openapitools.client.auth;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import org.apache.oltu.oauth2.client.HttpClient;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
public class OAuthOkHttpClient implements HttpClient {
private OkHttpClient client;
public OAuthOkHttpClient() {
this.client = new OkHttpClient();
}
public OAuthOkHttpClient(OkHttpClient client) {
this.client = client;
}
@Override
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
MediaType mediaType = MediaType.parse("application/json");
Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri());
if(headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().equalsIgnoreCase("Content-Type")) {
mediaType = MediaType.parse(entry.getValue());
} else {
requestBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
}
RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null;
requestBuilder.method(requestMethod, body);
try {
Response response = client.newCall(requestBuilder.build()).execute();
return OAuthClientResponseFactory.createCustomResponse(
response.body().string(),
response.body().contentType().toString(),
response.code(),
responseClass);
} catch (IOException e) {
throw new OAuthSystemException(e);
}
}
@Override
public void shutdown() {
// Nothing to do here
}
}

View File

@@ -0,0 +1,147 @@
package org.openapitools.client.auth;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Map;
public class RetryingOAuth extends OAuth implements Interceptor {
private OAuthClient oAuthClient;
private TokenRequestBuilder tokenRequestBuilder;
public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) {
this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client));
this.tokenRequestBuilder = tokenRequestBuilder;
}
public RetryingOAuth(TokenRequestBuilder tokenRequestBuilder) {
this(new OkHttpClient(), tokenRequestBuilder);
}
public RetryingOAuth(
String tokenUrl,
String clientId,
GrantType grantType,
String clientSecret,
Map<String, String> parameters
) {
this(OAuthClientRequest.tokenLocation(tokenUrl)
.setClientId(clientId)
.setGrantType(grantType)
.setClientSecret(clientSecret));
if (parameters != null) {
for (String paramName : parameters.keySet()) {
tokenRequestBuilder.setParameter(paramName, parameters.get(paramName));
}
}
}
@Override
public Response intercept(Chain chain) throws IOException {
return retryingIntercept(chain, true);
}
private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException {
Request request = chain.request();
// If the request already has an authorization (e.g. Basic auth), proceed with the request as is
if (request.header("Authorization") != null) {
return chain.proceed(request);
}
// Get the token if it has not yet been acquired
if (getAccessToken() == null) {
updateAccessToken(null);
}
OAuthClientRequest oAuthRequest;
if (getAccessToken() != null) {
// Build the request
Request.Builder requestBuilder = request.newBuilder();
String requestAccessToken = getAccessToken();
try {
oAuthRequest =
new OAuthBearerClientRequest(request.urlString()).
setAccessToken(requestAccessToken).
buildHeaderMessage();
} catch (OAuthSystemException e) {
throw new IOException(e);
}
Map<String, String> headers = oAuthRequest.getHeaders();
for (String headerName : headers.keySet()) {
requestBuilder.addHeader(headerName, headers.get(headerName));
}
requestBuilder.url(oAuthRequest.getLocationUri());
// Execute the request
Response response = chain.proceed(requestBuilder.build());
// 401/403 response codes most likely indicate an expired access token, unless it happens two times in a row
if (
response != null &&
( response.code() == HttpURLConnection.HTTP_UNAUTHORIZED ||
response.code() == HttpURLConnection.HTTP_FORBIDDEN ) &&
updateTokenAndRetryOnAuthorizationFailure
) {
try {
if (updateAccessToken(requestAccessToken)) {
response.body().close();
return retryingIntercept(chain, false);
}
} catch (Exception e) {
response.body().close();
throw e;
}
}
return response;
}
else {
return chain.proceed(chain.request());
}
}
/*
* Returns true if the access token has been updated
*/
public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
try {
OAuthJSONAccessTokenResponse accessTokenResponse =
oAuthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
setAccessToken(accessTokenResponse.getAccessToken());
return !getAccessToken().equals(requestAccessToken);
}
} catch (OAuthSystemException | OAuthProblemException e) {
throw new IOException(e);
}
}
return false;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
this.tokenRequestBuilder = tokenRequestBuilder;
}
}

View File

@@ -1,6 +1,6 @@
/*
* OpenAPI Petstore *_/ ' \" =end -- \\r\\n \\n \\r
* This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end --
* This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ *_/ ' \" =end --
*
* OpenAPI spec version: 1.0.0 *_/ ' \" =end -- \\r\\n \\n \\r
* Contact: something@something.abc *_/ ' \" =end -- \\r\\n \\n \\r
@@ -13,11 +13,16 @@
package org.openapitools.client.model;
import java.util.Objects;
import java.util.Arrays;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Objects;
import java.io.IOException;
/**
* Model for testing reserved words *_/ &#39; \&quot; &#x3D;end -- \\r\\n \\n \\r
@@ -70,7 +75,7 @@ public class ModelReturn {
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class ModelReturn {\n");
sb.append(" _return: ").append(toIndentedString(_return)).append("\n");
sb.append("}");
return sb.toString();

View File

@@ -99,6 +99,7 @@ dependencies {
compile 'com.squareup.okhttp:logging-interceptor:2.7.5'
compile 'com.google.code.gson:gson:2.8.1'
compile 'io.gsonfire:gson-fire:1.8.0'
compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1'
compile 'org.threeten:threetenbp:1.3.5'
testCompile 'junit:junit:4.12'
}

View File

@@ -212,6 +212,11 @@
<groupId>io.gsonfire</groupId>
<artifactId>gson-fire</artifactId>
<version>${gson-fire-version}</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.threeten</groupId>

View File

@@ -23,6 +23,9 @@ import org.threeten.bp.LocalDate;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.format.DateTimeFormatter;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
@@ -49,6 +52,7 @@ import org.openapitools.client.auth.Authentication;
import org.openapitools.client.auth.HttpBasicAuth;
import org.openapitools.client.auth.ApiKeyAuth;
import org.openapitools.client.auth.OAuth;
import org.openapitools.client.auth.RetryingOAuth;
public class ApiClient {
@@ -77,6 +81,39 @@ public class ApiClient {
* Constructor for ApiClient
*/
public ApiClient() {
init();
// Setup authentications (key: authentication name, value: authentication).
authentications.put("api_key", new ApiKeyAuth("header", "api_key"));
authentications.put("api_key_query", new ApiKeyAuth("query", "api_key_query"));
authentications.put("http_basic_test", new HttpBasicAuth());
authentications.put("petstore_auth", new OAuth());
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
/*
* Constructor for ApiClient to support access token retry on 401/403
*/
public ApiClient(
String clientId,
String clientSecret,
Map<String, String> parameters
) {
init();
RetryingOAuth retryingOAuth = new RetryingOAuth("", clientId, GrantType.valueOf("implicit"), clientSecret, parameters);
authentications.put(
"petstore_auth",
retryingOAuth
);
httpClient.interceptors().add(retryingOAuth);
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
private void init() {
httpClient = new OkHttpClient();
@@ -87,14 +124,7 @@ public class ApiClient {
// Set default User-Agent.
setUserAgent("OpenAPI-Generator/1.0.0/java");
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();
authentications.put("api_key", new ApiKeyAuth("header", "api_key"));
authentications.put("api_key_query", new ApiKeyAuth("query", "api_key_query"));
authentications.put("http_basic_test", new HttpBasicAuth());
authentications.put("petstore_auth", new OAuth());
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
/**
@@ -484,6 +514,20 @@ public class ApiClient {
return this;
}
/**
* Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one)
* @return Token request builder
*/
public TokenRequestBuilder getTokenEndPoint() {
for (Authentication apiAuth : authentications.values()) {
if (apiAuth instanceof RetryingOAuth) {
RetryingOAuth retryingOAuth = (RetryingOAuth) apiAuth;
return retryingOAuth.getTokenRequestBuilder();
}
}
return null;
}
/**
* Format the given parameter object into string.
*

View File

@@ -0,0 +1,68 @@
package org.openapitools.client.auth;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import org.apache.oltu.oauth2.client.HttpClient;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
public class OAuthOkHttpClient implements HttpClient {
private OkHttpClient client;
public OAuthOkHttpClient() {
this.client = new OkHttpClient();
}
public OAuthOkHttpClient(OkHttpClient client) {
this.client = client;
}
@Override
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
MediaType mediaType = MediaType.parse("application/json");
Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri());
if(headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().equalsIgnoreCase("Content-Type")) {
mediaType = MediaType.parse(entry.getValue());
} else {
requestBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
}
RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null;
requestBuilder.method(requestMethod, body);
try {
Response response = client.newCall(requestBuilder.build()).execute();
return OAuthClientResponseFactory.createCustomResponse(
response.body().string(),
response.body().contentType().toString(),
response.code(),
responseClass);
} catch (IOException e) {
throw new OAuthSystemException(e);
}
}
@Override
public void shutdown() {
// Nothing to do here
}
}

View File

@@ -0,0 +1,147 @@
package org.openapitools.client.auth;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Map;
public class RetryingOAuth extends OAuth implements Interceptor {
private OAuthClient oAuthClient;
private TokenRequestBuilder tokenRequestBuilder;
public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) {
this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client));
this.tokenRequestBuilder = tokenRequestBuilder;
}
public RetryingOAuth(TokenRequestBuilder tokenRequestBuilder) {
this(new OkHttpClient(), tokenRequestBuilder);
}
public RetryingOAuth(
String tokenUrl,
String clientId,
GrantType grantType,
String clientSecret,
Map<String, String> parameters
) {
this(OAuthClientRequest.tokenLocation(tokenUrl)
.setClientId(clientId)
.setGrantType(grantType)
.setClientSecret(clientSecret));
if (parameters != null) {
for (String paramName : parameters.keySet()) {
tokenRequestBuilder.setParameter(paramName, parameters.get(paramName));
}
}
}
@Override
public Response intercept(Chain chain) throws IOException {
return retryingIntercept(chain, true);
}
private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException {
Request request = chain.request();
// If the request already has an authorization (e.g. Basic auth), proceed with the request as is
if (request.header("Authorization") != null) {
return chain.proceed(request);
}
// Get the token if it has not yet been acquired
if (getAccessToken() == null) {
updateAccessToken(null);
}
OAuthClientRequest oAuthRequest;
if (getAccessToken() != null) {
// Build the request
Request.Builder requestBuilder = request.newBuilder();
String requestAccessToken = getAccessToken();
try {
oAuthRequest =
new OAuthBearerClientRequest(request.urlString()).
setAccessToken(requestAccessToken).
buildHeaderMessage();
} catch (OAuthSystemException e) {
throw new IOException(e);
}
Map<String, String> headers = oAuthRequest.getHeaders();
for (String headerName : headers.keySet()) {
requestBuilder.addHeader(headerName, headers.get(headerName));
}
requestBuilder.url(oAuthRequest.getLocationUri());
// Execute the request
Response response = chain.proceed(requestBuilder.build());
// 401/403 response codes most likely indicate an expired access token, unless it happens two times in a row
if (
response != null &&
( response.code() == HttpURLConnection.HTTP_UNAUTHORIZED ||
response.code() == HttpURLConnection.HTTP_FORBIDDEN ) &&
updateTokenAndRetryOnAuthorizationFailure
) {
try {
if (updateAccessToken(requestAccessToken)) {
response.body().close();
return retryingIntercept(chain, false);
}
} catch (Exception e) {
response.body().close();
throw e;
}
}
return response;
}
else {
return chain.proceed(chain.request());
}
}
/*
* Returns true if the access token has been updated
*/
public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
try {
OAuthJSONAccessTokenResponse accessTokenResponse =
oAuthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
setAccessToken(accessTokenResponse.getAccessToken());
return !getAccessToken().equals(requestAccessToken);
}
} catch (OAuthSystemException | OAuthProblemException e) {
throw new IOException(e);
}
}
return false;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
this.tokenRequestBuilder = tokenRequestBuilder;
}
}

View File

@@ -99,6 +99,7 @@ dependencies {
compile 'com.squareup.okhttp:logging-interceptor:2.7.5'
compile 'com.google.code.gson:gson:2.8.1'
compile 'io.gsonfire:gson-fire:1.8.0'
compile group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1'
compile 'org.threeten:threetenbp:1.3.5'
testCompile 'junit:junit:4.12'
}

View File

@@ -212,6 +212,11 @@
<groupId>io.gsonfire</groupId>
<artifactId>gson-fire</artifactId>
<version>${gson-fire-version}</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.threeten</groupId>

View File

@@ -23,6 +23,9 @@ import org.threeten.bp.LocalDate;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.format.DateTimeFormatter;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
@@ -49,6 +52,7 @@ import org.openapitools.client.auth.Authentication;
import org.openapitools.client.auth.HttpBasicAuth;
import org.openapitools.client.auth.ApiKeyAuth;
import org.openapitools.client.auth.OAuth;
import org.openapitools.client.auth.RetryingOAuth;
public class ApiClient {
@@ -77,6 +81,39 @@ public class ApiClient {
* Constructor for ApiClient
*/
public ApiClient() {
init();
// Setup authentications (key: authentication name, value: authentication).
authentications.put("api_key", new ApiKeyAuth("header", "api_key"));
authentications.put("api_key_query", new ApiKeyAuth("query", "api_key_query"));
authentications.put("http_basic_test", new HttpBasicAuth());
authentications.put("petstore_auth", new OAuth());
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
/*
* Constructor for ApiClient to support access token retry on 401/403
*/
public ApiClient(
String clientId,
String clientSecret,
Map<String, String> parameters
) {
init();
RetryingOAuth retryingOAuth = new RetryingOAuth("", clientId, GrantType.valueOf("implicit"), clientSecret, parameters);
authentications.put(
"petstore_auth",
retryingOAuth
);
httpClient.interceptors().add(retryingOAuth);
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
private void init() {
httpClient = new OkHttpClient();
@@ -87,14 +124,7 @@ public class ApiClient {
// Set default User-Agent.
setUserAgent("OpenAPI-Generator/1.0.0/java");
// Setup authentications (key: authentication name, value: authentication).
authentications = new HashMap<String, Authentication>();
authentications.put("api_key", new ApiKeyAuth("header", "api_key"));
authentications.put("api_key_query", new ApiKeyAuth("query", "api_key_query"));
authentications.put("http_basic_test", new HttpBasicAuth());
authentications.put("petstore_auth", new OAuth());
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
/**
@@ -484,6 +514,20 @@ public class ApiClient {
return this;
}
/**
* Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one)
* @return Token request builder
*/
public TokenRequestBuilder getTokenEndPoint() {
for (Authentication apiAuth : authentications.values()) {
if (apiAuth instanceof RetryingOAuth) {
RetryingOAuth retryingOAuth = (RetryingOAuth) apiAuth;
return retryingOAuth.getTokenRequestBuilder();
}
}
return null;
}
/**
* Format the given parameter object into string.
*

View File

@@ -0,0 +1,68 @@
package org.openapitools.client.auth;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import org.apache.oltu.oauth2.client.HttpClient;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
public class OAuthOkHttpClient implements HttpClient {
private OkHttpClient client;
public OAuthOkHttpClient() {
this.client = new OkHttpClient();
}
public OAuthOkHttpClient(OkHttpClient client) {
this.client = client;
}
@Override
public <T extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
MediaType mediaType = MediaType.parse("application/json");
Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri());
if(headers != null) {
for (Entry<String, String> entry : headers.entrySet()) {
if (entry.getKey().equalsIgnoreCase("Content-Type")) {
mediaType = MediaType.parse(entry.getValue());
} else {
requestBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
}
RequestBody body = request.getBody() != null ? RequestBody.create(mediaType, request.getBody()) : null;
requestBuilder.method(requestMethod, body);
try {
Response response = client.newCall(requestBuilder.build()).execute();
return OAuthClientResponseFactory.createCustomResponse(
response.body().string(),
response.body().contentType().toString(),
response.code(),
responseClass);
} catch (IOException e) {
throw new OAuthSystemException(e);
}
}
@Override
public void shutdown() {
// Nothing to do here
}
}

View File

@@ -0,0 +1,147 @@
package org.openapitools.client.auth;
import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.apache.oltu.oauth2.client.OAuthClient;
import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest;
import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder;
import org.apache.oltu.oauth2.client.response.OAuthJSONAccessTokenResponse;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.types.GrantType;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Map;
public class RetryingOAuth extends OAuth implements Interceptor {
private OAuthClient oAuthClient;
private TokenRequestBuilder tokenRequestBuilder;
public RetryingOAuth(OkHttpClient client, TokenRequestBuilder tokenRequestBuilder) {
this.oAuthClient = new OAuthClient(new OAuthOkHttpClient(client));
this.tokenRequestBuilder = tokenRequestBuilder;
}
public RetryingOAuth(TokenRequestBuilder tokenRequestBuilder) {
this(new OkHttpClient(), tokenRequestBuilder);
}
public RetryingOAuth(
String tokenUrl,
String clientId,
GrantType grantType,
String clientSecret,
Map<String, String> parameters
) {
this(OAuthClientRequest.tokenLocation(tokenUrl)
.setClientId(clientId)
.setGrantType(grantType)
.setClientSecret(clientSecret));
if (parameters != null) {
for (String paramName : parameters.keySet()) {
tokenRequestBuilder.setParameter(paramName, parameters.get(paramName));
}
}
}
@Override
public Response intercept(Chain chain) throws IOException {
return retryingIntercept(chain, true);
}
private Response retryingIntercept(Chain chain, boolean updateTokenAndRetryOnAuthorizationFailure) throws IOException {
Request request = chain.request();
// If the request already has an authorization (e.g. Basic auth), proceed with the request as is
if (request.header("Authorization") != null) {
return chain.proceed(request);
}
// Get the token if it has not yet been acquired
if (getAccessToken() == null) {
updateAccessToken(null);
}
OAuthClientRequest oAuthRequest;
if (getAccessToken() != null) {
// Build the request
Request.Builder requestBuilder = request.newBuilder();
String requestAccessToken = getAccessToken();
try {
oAuthRequest =
new OAuthBearerClientRequest(request.urlString()).
setAccessToken(requestAccessToken).
buildHeaderMessage();
} catch (OAuthSystemException e) {
throw new IOException(e);
}
Map<String, String> headers = oAuthRequest.getHeaders();
for (String headerName : headers.keySet()) {
requestBuilder.addHeader(headerName, headers.get(headerName));
}
requestBuilder.url(oAuthRequest.getLocationUri());
// Execute the request
Response response = chain.proceed(requestBuilder.build());
// 401/403 response codes most likely indicate an expired access token, unless it happens two times in a row
if (
response != null &&
( response.code() == HttpURLConnection.HTTP_UNAUTHORIZED ||
response.code() == HttpURLConnection.HTTP_FORBIDDEN ) &&
updateTokenAndRetryOnAuthorizationFailure
) {
try {
if (updateAccessToken(requestAccessToken)) {
response.body().close();
return retryingIntercept(chain, false);
}
} catch (Exception e) {
response.body().close();
throw e;
}
}
return response;
}
else {
return chain.proceed(chain.request());
}
}
/*
* Returns true if the access token has been updated
*/
public synchronized boolean updateAccessToken(String requestAccessToken) throws IOException {
if (getAccessToken() == null || getAccessToken().equals(requestAccessToken)) {
try {
OAuthJSONAccessTokenResponse accessTokenResponse =
oAuthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) {
setAccessToken(accessTokenResponse.getAccessToken());
return !getAccessToken().equals(requestAccessToken);
}
} catch (OAuthSystemException | OAuthProblemException e) {
throw new IOException(e);
}
}
return false;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) {
this.tokenRequestBuilder = tokenRequestBuilder;
}
}