From 9e42e160175568038f310a91348acc7fbc090759 Mon Sep 17 00:00:00 2001 From: Mauro Valota <maurovalota@fattureincloud.it> Date: Fri, 29 Oct 2021 17:23:20 +0200 Subject: [PATCH 1/7] replaces oltu with scribejava for java okhttp --- .../codegen/languages/JavaClientCodegen.java | 7 +- .../libraries/okhttp-gson/ApiClient.mustache | 145 ++++++++------ .../auth/DefaultApi20Impl.mustache | 67 +++++++ .../auth/OAuthAuthorizationCodeGrant.mustache | 108 +++++++++++ .../auth/OAuthClientCredentialsGrant.mustache | 66 +++++++ .../auth/OAuthOkHttpClient.mustache | 70 ------- .../auth/OAuthPasswordGrant.mustache | 83 ++++++++ .../okhttp-gson/auth/RetryingOAuth.mustache | 181 ------------------ .../okhttp-gson/build.gradle.mustache | 3 +- .../libraries/okhttp-gson/build.sbt.mustache | 3 +- .../Java/libraries/okhttp-gson/pom.mustache | 13 +- .../codegen/DefaultGeneratorTest.java | 2 +- 12 files changed, 425 insertions(+), 323 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/DefaultApi20Impl.mustache create mode 100644 modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthAuthorizationCodeGrant.mustache create mode 100644 modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthClientCredentialsGrant.mustache delete mode 100644 modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache create mode 100644 modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthPasswordGrant.mustache delete mode 100644 modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/RetryingOAuth.mustache diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java index 1e2740f1858..98c470e9b8b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java @@ -616,8 +616,11 @@ public class JavaClientCodegen extends AbstractJavaCodegen if (ProcessUtils.hasOAuthMethods(openAPI)) { // for okhttp-gson (default), check to see if OAuth is defined and included OAuth-related files accordingly if ((OKHTTP_GSON.equals(getLibrary()) || StringUtils.isEmpty(getLibrary()))) { - supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java")); - supportingFiles.add(new SupportingFile("auth/RetryingOAuth.mustache", authFolder, "RetryingOAuth.java")); + supportingFiles.add(new SupportingFile("auth/DefaultApi20Impl.mustache", authFolder, "DefaultApi20Impl.java")); + supportingFiles.add(new SupportingFile("auth/OAuthAuthorizationCodeGrant.mustache", authFolder, "OAuthAuthorizationCodeGrant.java")); + supportingFiles.add(new SupportingFile("auth/OAuthClientCredentialsGrant.mustache", authFolder, "OAuthClientCredentialsGrant.java")); + supportingFiles.add(new SupportingFile("auth/OAuthPasswordGrant.mustache", authFolder, "OAuthPasswordGrant.java")); + } // google-api-client doesn't use the OpenAPI auth, because it uses Google Credential directly (HttpRequestInitializer) diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache index 357d8c71d0c..a54ee35634f 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache @@ -27,10 +27,6 @@ import org.threeten.bp.LocalDate; import org.threeten.bp.OffsetDateTime; import org.threeten.bp.format.DateTimeFormatter; {{/threetenbp}} -{{#hasOAuthMethods}} -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -import org.apache.oltu.oauth2.common.message.types.GrantType; -{{/hasOAuthMethods}} import javax.net.ssl.*; import java.io.File; @@ -62,15 +58,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import {{invokerPackage}}.auth.Authentication; -import {{invokerPackage}}.auth.HttpBasicAuth; -import {{invokerPackage}}.auth.HttpBearerAuth; -import {{invokerPackage}}.auth.ApiKeyAuth; -{{#hasOAuthMethods}} -import {{invokerPackage}}.auth.OAuth; -import {{invokerPackage}}.auth.RetryingOAuth; -import {{invokerPackage}}.auth.OAuthFlow; -{{/hasOAuthMethods}} +import {{invokerPackage}}.auth.*; public class ApiClient { @@ -158,31 +146,55 @@ public class ApiClient { } /* - * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + * Constructor for ApiClient configured with base path, client ID, secret, and additional parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map<String, String> parameters) { + this(basePath, clientId, clientSecret, null, null, parameters); + } + + /* + * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + */ + public ApiClient(String basePath, String clientId, String clientSecret, String scope, String callbackUrl, Map<String, String> parameters) { init(); if (basePath != null) { this.basePath = basePath; } {{#hasOAuthMethods}} - String tokenUrl = "{{tokenUrl}}"; - if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) { - URI uri = URI.create(getBasePath()); - tokenUrl = uri.getScheme() + ":" + - (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + - tokenUrl; - if (!URI.create(tokenUrl).isAbsolute()) { - throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); - } + initHttpClient(); + + {{^java8}} + switch(OAuthFlow.{{flow}}) { + case accessCode: + authentications.put("{{name}}", new OAuthAuthorizationCodeGrant(clientId, clientSecret, scope, getAuthorizationUrl(), getTokenUrl(), callbackUrl, getRefreshUrl(), parameters, this.httpClient)); + break; + case password: + authentications.put("{{name}}", new OAuthPasswordGrant(clientId, clientSecret, scope, getTokenUrl(), getRefreshUrl(), this.httpClient)); + break; + case application: + authentications.put("{{name}}", new OAuthClientCredentialsGrant(clientId, clientSecret, scope, getTokenUrl(), this.httpClient)); + break; + default: + throw new IllegalArgumentException("OAuth flow not implemented"); + } + {{/java8}} + {{#java8}} + switch(OAuthFlow.{{flow}}) { + case accessCode: + authentications.put("{{name}}", new OAuthAuthorizationCodeGrant(clientId, clientSecret, Optional.of(scope), getAuthorizationUrl(), getTokenUrl(), callbackUrl, getRefreshUrl(), parameters, this.httpClient)); + break; + case password: + authentications.put("{{name}}", new OAuthPasswordGrant(clientId, clientSecret, scope, getTokenUrl(), getRefreshUrl(), this.httpClient)); + break; + case application: + authentications.put("{{name}}", new OAuthClientCredentialsGrant(clientId, clientSecret, scope, getTokenUrl(), this.httpClient)); + break; + default: + throw new IllegalArgumentException("OAuth flow not implemented"); } - RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.{{flow}}, clientSecret, parameters); - authentications.put( - "{{name}}", - retryingOAuth - ); - initHttpClient(Collections.<Interceptor>singletonList(retryingOAuth)); + {{/java8}} + {{/hasOAuthMethods}} // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} @@ -193,6 +205,47 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } +{{#hasOAuthMethods}} + private String getTokenUrl() { + try { + return getAbsoluteUrl("{{tokenUrl}}"); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); + } + } + + private String getAuthorizationUrl() { + try { + return getAbsoluteUrl("{{authorizationUrl}}"); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 authorization URL must be an absolute URL"); + } + } + + private String getRefreshUrl() { + try { + return getAbsoluteUrl("{{refreshUrl}}"); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 authorization URL must be an absolute URL"); + } + } + + private String getAbsoluteUrl(String url) throws IllegalArgumentException { + if (!"".equals(url) && !URI.create(url).isAbsolute()) { + URI uri = URI.create(getBasePath()); + String absoluteUrl = uri.getScheme() + ":" + + (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + + url; + if (!URI.create(absoluteUrl).isAbsolute()) { + throw new IllegalArgumentException("Unable to obtain an absolute URL"); + } + return absoluteUrl; + } else { + return url; + } + } +{{/hasOAuthMethods}} + {{/-first}} {{/oauthMethods}} {{/hasOAuthMethods}} @@ -664,23 +717,6 @@ public class ApiClient { return this; } - {{#hasOAuthMethods}} - /** - * 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; - } - {{/hasOAuthMethods}} - /** * Format the given parameter object into string. * @@ -1123,23 +1159,6 @@ public class ApiClient { } } - {{#supportStreaming}} - public InputStream executeStream(Call call, Type returnType) throws ApiException { - try { - Response response = call.execute(); - if (!response.isSuccessful()) { - throw new ApiException(response.code(), response.message()); - } - if (response.body() == null) { - return null; - } - return response.body().byteStream(); - } catch (IOException e) { - throw new ApiException(e); - } - } - - {{/supportStreaming}} /** * {@link #executeAsync(Call, Type, ApiCallback)} * diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/DefaultApi20Impl.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/DefaultApi20Impl.mustache new file mode 100644 index 00000000000..8afe4b2382c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/DefaultApi20Impl.mustache @@ -0,0 +1,67 @@ +{{#hasOAuthMethods}} +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +{{>generatedAnnotation}} +public class DefaultApi20Impl extends DefaultApi20 { + + private final String accessTokenEndpoint; + private final String authorizationBaseUrl; + private final String refreshTokenEndpoint; + + protected DefaultApi20Impl(String accessTokenEndpoint) { + this(accessTokenEndpoint, null, null); + } + + protected DefaultApi20Impl(String accessTokenEndpoint, String refreshTokenEndpoint) { + this(accessTokenEndpoint, null, refreshTokenEndpoint); + } + + protected DefaultApi20Impl(String accessTokenEndpoint, String authorizationBaseUrl, String refreshTokenEndpoint) { + this.accessTokenEndpoint = accessTokenEndpoint; + this.authorizationBaseUrl = authorizationBaseUrl; + this.refreshTokenEndpoint = refreshTokenEndpoint; + } + + @Override + public String getRefreshTokenEndpoint() { + if (this.refreshTokenEndpoint == null || this.refreshTokenEndpoint.trim().isEmpty()) { + return this.getAccessTokenEndpoint(); + } + return this.refreshTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return this.authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor<OAuth2AccessToken> getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} +{{/hasOAuthMethods}} diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthAuthorizationCodeGrant.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthAuthorizationCodeGrant.mustache new file mode 100644 index 00000000000..eabf2a6df81 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthAuthorizationCodeGrant.mustache @@ -0,0 +1,108 @@ +{{#hasOAuthMethods}} +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2Authorization; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +{{>generatedAnnotation}} +public class OAuthAuthorizationCodeGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + private Map<String, String> params; + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map<String, String> params) { + this(clientId, clientSecret, null, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, null, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map<String, String> params) { + this(clientId, clientSecret, scope, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, null, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, String refreshUrl, Map<String, String> params) { + this(clientId, clientSecret, scope, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, refreshUrl, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, String refreshUrl, Map<String, String> params, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, authorizationBaseUrl, refreshUrl); + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback(callbackUrl); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + + this.service = serviceBuilder.build(this.apiInstance); + + this.params = params; + } + + public String getAuthorizationUrl(String state) { + if (state != null && !state.trim().isEmpty()) { + return this.service.getAuthorizationUrl(state); + } else { + return this.service.getAuthorizationUrl(); + } + } + + public OAuth2Authorization extractAuthorization(String redirectLocation) { + return service.extractAuthorization(redirectLocation); + } + + public OAuth2AccessToken obtainAccessToken(OAuth2Authorization authorization, String scope) throws IOException, ExecutionException, InterruptedException { + return this.obtainAccessToken(authorization.getCode(), scope); + } + + public OAuth2AccessToken obtainAccessToken(String code, String scope) throws IOException, ExecutionException, InterruptedException { + AccessTokenRequestParams reqParams = new AccessTokenRequestParams(code); + reqParams.addExtraParameters(params); + + if (scope != null && !scope.trim().isEmpty()) { + reqParams.scope(scope); + } + + OAuth2AccessToken tokenResponse = service.getAccessToken(reqParams); + + this.setAccessToken(tokenResponse.getAccessToken()); + return tokenResponse; + } + + + public void setToken(OAuth2AccessToken token) { + this.setAccessToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setAccessToken(accessToken); + } + + public OAuth2AccessToken refreshToken(OAuth2AccessToken token, String scope) throws IOException, ExecutionException, InterruptedException { + return this.refreshToken(token.getRefreshToken(), scope); + } + + public OAuth2AccessToken refreshToken(String refreshToken, String scope) throws IOException, ExecutionException, InterruptedException { + if (scope != null && !scope.trim().isEmpty()) { + return this.service.refreshAccessToken(refreshToken, scope); + } else { + return this.service.refreshAccessToken(refreshToken); + } + } + +} +{{/hasOAuthMethods}} diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthClientCredentialsGrant.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthClientCredentialsGrant.mustache new file mode 100644 index 00000000000..343d7691dd2 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthClientCredentialsGrant.mustache @@ -0,0 +1,66 @@ +{{#hasOAuthMethods}} +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +{{>generatedAnnotation}} +public class OAuthClientCredentialsGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String accessTokenEndpoint) { + this(clientId, clientSecret, null, accessTokenEndpoint, null); + } + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint) { + this(clientId, clientSecret, scope, accessTokenEndpoint, null); + } + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, null, null); + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + this.service = serviceBuilder.build(this.apiInstance); + } + + public OAuth2AccessToken obtainAccessToken(String scope) throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken tokenResponse; + if (scope != null && !scope.trim().isEmpty()) { + tokenResponse = service.getAccessTokenClientCredentialsGrant(scope); + } else { + tokenResponse = service.getAccessTokenClientCredentialsGrant(); + } + + this.setAccessToken(tokenResponse.getAccessToken()); + + return tokenResponse; + } + + public void setToken(OAuth2AccessToken token) { + this.setToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setAccessToken(accessToken); + } + +} +{{/hasOAuthMethods}} diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache deleted file mode 100644 index cb0e8250550..00000000000 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthOkHttpClient.mustache +++ /dev/null @@ -1,70 +0,0 @@ -{{#hasOAuthMethods}} -package {{invokerPackage}}.auth; - -import okhttp3.OkHttpClient; -import okhttp3.MediaType; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.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(request.getBody(), mediaType) : 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 - } -} -{{/hasOAuthMethods}} diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthPasswordGrant.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthPasswordGrant.mustache new file mode 100644 index 00000000000..3b51a3cd3f9 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthPasswordGrant.mustache @@ -0,0 +1,83 @@ +{{#hasOAuthMethods}} +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +{{>generatedAnnotation}} +public class OAuthPasswordGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + + public OAuthPasswordGrant(String clientId, String clientSecret, String accessTokenEndpoint) { + this(clientId, clientSecret, null, accessTokenEndpoint, null, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint) { + this(clientId, clientSecret, scope, accessTokenEndpoint, null, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, String refreshTokenUrl) { + this(clientId, clientSecret, scope, accessTokenEndpoint, refreshTokenUrl, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, String refreshTokenUrl, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, null, refreshTokenUrl); + + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + this.service = serviceBuilder.build(this.apiInstance); + } + + public OAuth2AccessToken obtainAccessToken(String username, String password) throws IOException, ExecutionException, InterruptedException { + return this.obtainAccessToken(username, password, null); + } + + public OAuth2AccessToken obtainAccessToken(String username, String password, String scope) throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken tokenResponse; + if (scope != null && !scope.trim().isEmpty()) { + tokenResponse = service.getAccessTokenPasswordGrant(username, password, scope); + } else { + tokenResponse = service.getAccessTokenPasswordGrant(username, password); + } + + this.setAccessToken(tokenResponse.getAccessToken()); + + return tokenResponse; + } + + public void setToken(OAuth2AccessToken token) { + this.setToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setToken(accessToken); + } + + public OAuth2AccessToken refreshToken(OAuth2AccessToken token) throws IOException, ExecutionException, InterruptedException { + return this.refreshToken(token.getRefreshToken()); + } + + public OAuth2AccessToken refreshToken(String refreshToken) throws IOException, ExecutionException, InterruptedException { + return this.service.refreshAccessToken(refreshToken); + } + +} +{{/hasOAuthMethods}} diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/RetryingOAuth.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/RetryingOAuth.mustache deleted file mode 100644 index 6e6562448da..00000000000 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ /dev/null @@ -1,181 +0,0 @@ -{{#hasOAuthMethods}} -package {{invokerPackage}}.auth; - -import {{invokerPackage}}.Pair; - -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.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; -import java.util.List; - -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); - } - - /** - @param tokenUrl The token URL to be used for this OAuth2 flow. - Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode". - The value must be an absolute URL. - @param clientId The OAuth2 client ID for the "clientCredentials" flow. - @param clientSecret The OAuth2 client secret for the "clientCredentials" flow. - */ - public RetryingOAuth( - String tokenUrl, - String clientId, - OAuthFlow flow, - String clientSecret, - Map<String, String> parameters - ) { - this(OAuthClientRequest.tokenLocation(tokenUrl) - .setClientId(clientId) - .setClientSecret(clientSecret)); - setFlow(flow); - if (parameters != null) { - for (String paramName : parameters.keySet()) { - tokenRequestBuilder.setParameter(paramName, parameters.get(paramName)); - } - } - } - - public void setFlow(OAuthFlow flow) { - switch(flow) { - case accessCode: - tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); - break; - case implicit: - tokenRequestBuilder.setGrantType(GrantType.IMPLICIT); - break; - case password: - tokenRequestBuilder.setGrantType(GrantType.PASSWORD); - break; - case application: - tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); - break; - default: - break; - } - } - - @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.url().toString()). - 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()); - } - } catch (OAuthSystemException | OAuthProblemException e) { - throw new IOException(e); - } - } - return getAccessToken() == null || !getAccessToken().equals(requestAccessToken); - } - - public TokenRequestBuilder getTokenRequestBuilder() { - return tokenRequestBuilder; - } - - public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { - this.tokenRequestBuilder = tokenRequestBuilder; - } - - // Applying authorization to parameters is performed in the retryingIntercept method - @Override - public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams, Map<String, String> cookieParams) { - // No implementation necessary - } -} -{{/hasOAuthMethods}} diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache index 90342173dd6..09c0f8783dd 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.gradle.mustache @@ -118,7 +118,8 @@ dependencies { implementation 'org.openapitools:jackson-databind-nullable:0.2.1' {{/openApiNullable}} {{#hasOAuthMethods}} - implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + implementation group: 'com.github.scribejava', name: 'scribejava-core', version: '8.3.1' + implementation group: 'com.github.scribejava', name: 'scribejava-httpclient-okhttp', version: '8.3.1' {{/hasOAuthMethods}} implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' {{#joda}} diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.sbt.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.sbt.mustache index 907e8a916ec..3d1b43dfec3 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.sbt.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/build.sbt.mustache @@ -18,7 +18,8 @@ lazy val root = (project in file(".")). "org.openapitools" % "jackson-databind-nullable" % "0.2.1", {{/openApiNullable}} {{#hasOAuthMethods}} - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", + "com.github.scribejava" % "scribejava-core" % "8.3.1", + "com.github.scribejava" % "scribejava-httpclient-okhttp" % "8.3.1", {{/hasOAuthMethods}} {{#joda}} "joda-time" % "joda-time" % "2.9.9" % "compile", diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pom.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pom.mustache index 6cd8e351291..8d64ffccf13 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pom.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pom.mustache @@ -247,9 +247,14 @@ </dependency> {{#hasOAuthMethods}} <dependency> - <groupId>org.apache.oltu.oauth2</groupId> - <artifactId>org.apache.oltu.oauth2.client</artifactId> - <version>1.0.1</version> + <groupId>com.github.scribejava</groupId> + <artifactId>scribejava-core</artifactId> + <version>8.3.1</version> + </dependency> + <dependency> + <groupId>com.github.scribejava</groupId> + <artifactId>scribejava-httpclient-okhttp</artifactId> + <version>8.3.1</version> </dependency> {{/hasOAuthMethods}} <dependency> @@ -359,7 +364,7 @@ <jakarta.el-version>3.0.3</jakarta.el-version> {{/performBeanValidation}} {{#useBeanValidation}} - <beanvalidation-version>2.0.2</beanvalidation-version> + <beanvalidation-version>2.0.2</beanvalidation-version> {{/useBeanValidation}} <junit-version>4.13.2</junit-version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java index 81869d78f91..9e3d4f82877 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultGeneratorTest.java @@ -64,7 +64,7 @@ public class DefaultGeneratorTest { List<File> files = generator.opts(clientOptInput).generate(); - Assert.assertEquals(files.size(), 42); + Assert.assertEquals(files.size(), 44); // Check expected generated files // api sanity check -- GitLab From fa841d17e4c3535f8fc8020b60e6376edd2dfb51 Mon Sep 17 00:00:00 2001 From: Mauro Valota <maurovalota@fattureincloud.it> Date: Fri, 29 Oct 2021 17:39:04 +0200 Subject: [PATCH 2/7] generated samples with scribejava --- .../org/openapitools/client/ApiClient.java | 21 +--- .../.openapi-generator/FILES | 6 +- .../build.gradle | 3 +- .../okhttp-gson-dynamicOperations/build.sbt | 3 +- .../okhttp-gson-dynamicOperations/pom.xml | 11 +- .../org/openapitools/client/ApiClient.java | 103 ++++++++++------- .../client/auth/DefaultApi20Impl.java | 65 +++++++++++ .../auth/OAuthAuthorizationCodeGrant.java | 106 ++++++++++++++++++ .../auth/OAuthClientCredentialsGrant.java | 64 +++++++++++ .../client/auth/OAuthPasswordGrant.java | 81 +++++++++++++ .../.openapi-generator/FILES | 6 +- .../okhttp-gson-parcelableModel/build.gradle | 3 +- .../okhttp-gson-parcelableModel/build.sbt | 3 +- .../java/okhttp-gson-parcelableModel/pom.xml | 11 +- .../org/openapitools/client/ApiClient.java | 103 ++++++++++------- .../client/auth/DefaultApi20Impl.java | 65 +++++++++++ .../auth/OAuthAuthorizationCodeGrant.java | 106 ++++++++++++++++++ .../auth/OAuthClientCredentialsGrant.java | 64 +++++++++++ .../client/auth/OAuthPasswordGrant.java | 81 +++++++++++++ .../java/okhttp-gson/.openapi-generator/FILES | 6 +- .../petstore/java/okhttp-gson/build.gradle | 3 +- .../petstore/java/okhttp-gson/build.sbt | 3 +- .../client/petstore/java/okhttp-gson/pom.xml | 11 +- .../org/openapitools/client/ApiClient.java | 103 ++++++++++------- .../client/auth/DefaultApi20Impl.java | 65 +++++++++++ .../auth/OAuthAuthorizationCodeGrant.java | 106 ++++++++++++++++++ .../auth/OAuthClientCredentialsGrant.java | 64 +++++++++++ .../client/auth/OAuthPasswordGrant.java | 81 +++++++++++++ 28 files changed, 1186 insertions(+), 161 deletions(-) create mode 100644 samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java create mode 100644 samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java create mode 100644 samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java create mode 100644 samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java create mode 100644 samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java create mode 100644 samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java create mode 100644 samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java create mode 100644 samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java create mode 100644 samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java create mode 100644 samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java create mode 100644 samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java create mode 100644 samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java diff --git a/samples/client/others/java/okhttp-gson-streaming/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/others/java/okhttp-gson-streaming/src/main/java/org/openapitools/client/ApiClient.java index c48b4479cc6..412081ae259 100644 --- a/samples/client/others/java/okhttp-gson-streaming/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/others/java/okhttp-gson-streaming/src/main/java/org/openapitools/client/ApiClient.java @@ -49,10 +49,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.openapitools.client.auth.Authentication; -import org.openapitools.client.auth.HttpBasicAuth; -import org.openapitools.client.auth.HttpBearerAuth; -import org.openapitools.client.auth.ApiKeyAuth; +import org.openapitools.client.auth.*; public class ApiClient { @@ -525,7 +522,6 @@ public class ApiClient { return this; } - /** * Format the given parameter object into string. * @@ -927,21 +923,6 @@ public class ApiClient { } } - public InputStream executeStream(Call call, Type returnType) throws ApiException { - try { - Response response = call.execute(); - if (!response.isSuccessful()) { - throw new ApiException(response.code(), response.message()); - } - if (response.body() == null) { - return null; - } - return response.body().byteStream(); - } catch (IOException e) { - throw new ApiException(e); - } - } - /** * {@link #executeAsync(Call, Type, ApiCallback)} * diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/.openapi-generator/FILES b/samples/client/petstore/java/okhttp-gson-dynamicOperations/.openapi-generator/FILES index 5597480c76d..de4fb2cb474 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/.openapi-generator/FILES +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/.openapi-generator/FILES @@ -86,12 +86,14 @@ src/main/java/org/openapitools/client/api/StoreApi.java src/main/java/org/openapitools/client/api/UserApi.java src/main/java/org/openapitools/client/auth/ApiKeyAuth.java src/main/java/org/openapitools/client/auth/Authentication.java +src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java src/main/java/org/openapitools/client/auth/HttpBasicAuth.java src/main/java/org/openapitools/client/auth/HttpBearerAuth.java src/main/java/org/openapitools/client/auth/OAuth.java +src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java +src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java src/main/java/org/openapitools/client/auth/OAuthFlow.java -src/main/java/org/openapitools/client/auth/OAuthOkHttpClient.java -src/main/java/org/openapitools/client/auth/RetryingOAuth.java +src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java src/main/java/org/openapitools/client/model/AdditionalPropertiesAnyType.java src/main/java/org/openapitools/client/model/AdditionalPropertiesArray.java src/main/java/org/openapitools/client/model/AdditionalPropertiesBoolean.java diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.gradle b/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.gradle index 24820c068c0..fa36503f806 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.gradle +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.gradle @@ -111,7 +111,8 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.6' implementation 'io.gsonfire:gson-fire:1.8.4' implementation 'org.openapitools:jackson-databind-nullable:0.2.1' - implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + implementation group: 'com.github.scribejava', name: 'scribejava-core', version: '8.3.1' + implementation group: 'com.github.scribejava', name: 'scribejava-httpclient-okhttp', version: '8.3.1' implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' implementation 'org.threeten:threetenbp:1.4.3' implementation 'io.swagger.parser.v3:swagger-parser-v3:2.0.23' diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.sbt b/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.sbt index 2957b77a9e6..1aec3e32f28 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.sbt +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.sbt @@ -15,7 +15,8 @@ lazy val root = (project in file(".")). "com.google.code.gson" % "gson" % "2.8.6", "org.apache.commons" % "commons-lang3" % "3.10", "org.openapitools" % "jackson-databind-nullable" % "0.2.1", - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", + "com.github.scribejava" % "scribejava-core" % "8.3.1", + "com.github.scribejava" % "scribejava-httpclient-okhttp" % "8.3.1", "org.threeten" % "threetenbp" % "1.4.3" % "compile", "io.swagger.parser.v3" % "swagger-parser-v3" "2.0.23" % "compile" "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/pom.xml b/samples/client/petstore/java/okhttp-gson-dynamicOperations/pom.xml index 3ce94aa5dd4..001378d4a31 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/pom.xml +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/pom.xml @@ -239,9 +239,14 @@ <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> + <groupId>com.github.scribejava</groupId> + <artifactId>scribejava-core</artifactId> + <version>8.3.1</version> + </dependency> + <dependency> + <groupId>com.github.scribejava</groupId> + <artifactId>scribejava-httpclient-okhttp</artifactId> + <version>8.3.1</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/ApiClient.java index e9e3861cdae..13f09144b6a 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/ApiClient.java @@ -29,8 +29,6 @@ import okio.Okio; 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; @@ -57,13 +55,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.openapitools.client.auth.Authentication; -import org.openapitools.client.auth.HttpBasicAuth; -import org.openapitools.client.auth.HttpBearerAuth; -import org.openapitools.client.auth.ApiKeyAuth; -import org.openapitools.client.auth.OAuth; -import org.openapitools.client.auth.RetryingOAuth; -import org.openapitools.client.auth.OAuthFlow; +import org.openapitools.client.auth.*; public class ApiClient { @@ -146,30 +138,37 @@ public class ApiClient { } /* - * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + * Constructor for ApiClient configured with base path, client ID, secret, and additional parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map<String, String> parameters) { + this(basePath, clientId, clientSecret, null, null, parameters); + } + + /* + * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + */ + public ApiClient(String basePath, String clientId, String clientSecret, String scope, String callbackUrl, Map<String, String> parameters) { init(); if (basePath != null) { this.basePath = basePath; } - String tokenUrl = ""; - if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) { - URI uri = URI.create(getBasePath()); - tokenUrl = uri.getScheme() + ":" + - (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + - tokenUrl; - if (!URI.create(tokenUrl).isAbsolute()) { - throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); - } + initHttpClient(); + + switch(OAuthFlow.implicit) { + case accessCode: + authentications.put("petstore_auth", new OAuthAuthorizationCodeGrant(clientId, clientSecret, scope, getAuthorizationUrl(), getTokenUrl(), callbackUrl, getRefreshUrl(), parameters, this.httpClient)); + break; + case password: + authentications.put("petstore_auth", new OAuthPasswordGrant(clientId, clientSecret, scope, getTokenUrl(), getRefreshUrl(), this.httpClient)); + break; + case application: + authentications.put("petstore_auth", new OAuthClientCredentialsGrant(clientId, clientSecret, scope, getTokenUrl(), this.httpClient)); + break; + default: + throw new IllegalArgumentException("OAuth flow not implemented"); } - RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.implicit, clientSecret, parameters); - authentications.put( - "petstore_auth", - retryingOAuth - ); - initHttpClient(Collections.<Interceptor>singletonList(retryingOAuth)); + // 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")); @@ -179,6 +178,45 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + private String getTokenUrl() { + try { + return getAbsoluteUrl(""); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); + } + } + + private String getAuthorizationUrl() { + try { + return getAbsoluteUrl("http://petstore.swagger.io/api/oauth/dialog"); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 authorization URL must be an absolute URL"); + } + } + + private String getRefreshUrl() { + try { + return getAbsoluteUrl(""); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 authorization URL must be an absolute URL"); + } + } + + private String getAbsoluteUrl(String url) throws IllegalArgumentException { + if (!"".equals(url) && !URI.create(url).isAbsolute()) { + URI uri = URI.create(getBasePath()); + String absoluteUrl = uri.getScheme() + ":" + + (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + + url; + if (!URI.create(absoluteUrl).isAbsolute()) { + throw new IllegalArgumentException("Unable to obtain an absolute URL"); + } + return absoluteUrl; + } else { + return url; + } + } + private void initHttpClient() { initHttpClient(Collections.<Interceptor>emptyList()); } @@ -610,21 +648,6 @@ 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. * diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java new file mode 100644 index 00000000000..c39eb1221a8 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java @@ -0,0 +1,65 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class DefaultApi20Impl extends DefaultApi20 { + + private final String accessTokenEndpoint; + private final String authorizationBaseUrl; + private final String refreshTokenEndpoint; + + protected DefaultApi20Impl(String accessTokenEndpoint) { + this(accessTokenEndpoint, null, null); + } + + protected DefaultApi20Impl(String accessTokenEndpoint, String refreshTokenEndpoint) { + this(accessTokenEndpoint, null, refreshTokenEndpoint); + } + + protected DefaultApi20Impl(String accessTokenEndpoint, String authorizationBaseUrl, String refreshTokenEndpoint) { + this.accessTokenEndpoint = accessTokenEndpoint; + this.authorizationBaseUrl = authorizationBaseUrl; + this.refreshTokenEndpoint = refreshTokenEndpoint; + } + + @Override + public String getRefreshTokenEndpoint() { + if (this.refreshTokenEndpoint == null || this.refreshTokenEndpoint.trim().isEmpty()) { + return this.getAccessTokenEndpoint(); + } + return this.refreshTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return this.authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor<OAuth2AccessToken> getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java new file mode 100644 index 00000000000..33eddbe51f2 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java @@ -0,0 +1,106 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2Authorization; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthAuthorizationCodeGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + private Map<String, String> params; + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map<String, String> params) { + this(clientId, clientSecret, null, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, null, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map<String, String> params) { + this(clientId, clientSecret, scope, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, null, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, String refreshUrl, Map<String, String> params) { + this(clientId, clientSecret, scope, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, refreshUrl, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, String refreshUrl, Map<String, String> params, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, authorizationBaseUrl, refreshUrl); + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback(callbackUrl); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + + this.service = serviceBuilder.build(this.apiInstance); + + this.params = params; + } + + public String getAuthorizationUrl(String state) { + if (state != null && !state.trim().isEmpty()) { + return this.service.getAuthorizationUrl(state); + } else { + return this.service.getAuthorizationUrl(); + } + } + + public OAuth2Authorization extractAuthorization(String redirectLocation) { + return service.extractAuthorization(redirectLocation); + } + + public OAuth2AccessToken obtainAccessToken(OAuth2Authorization authorization, String scope) throws IOException, ExecutionException, InterruptedException { + return this.obtainAccessToken(authorization.getCode(), scope); + } + + public OAuth2AccessToken obtainAccessToken(String code, String scope) throws IOException, ExecutionException, InterruptedException { + AccessTokenRequestParams reqParams = new AccessTokenRequestParams(code); + reqParams.addExtraParameters(params); + + if (scope != null && !scope.trim().isEmpty()) { + reqParams.scope(scope); + } + + OAuth2AccessToken tokenResponse = service.getAccessToken(reqParams); + + this.setAccessToken(tokenResponse.getAccessToken()); + return tokenResponse; + } + + + public void setToken(OAuth2AccessToken token) { + this.setAccessToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setAccessToken(accessToken); + } + + public OAuth2AccessToken refreshToken(OAuth2AccessToken token, String scope) throws IOException, ExecutionException, InterruptedException { + return this.refreshToken(token.getRefreshToken(), scope); + } + + public OAuth2AccessToken refreshToken(String refreshToken, String scope) throws IOException, ExecutionException, InterruptedException { + if (scope != null && !scope.trim().isEmpty()) { + return this.service.refreshAccessToken(refreshToken, scope); + } else { + return this.service.refreshAccessToken(refreshToken); + } + } + +} diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java new file mode 100644 index 00000000000..439728c6b46 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java @@ -0,0 +1,64 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthClientCredentialsGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String accessTokenEndpoint) { + this(clientId, clientSecret, null, accessTokenEndpoint, null); + } + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint) { + this(clientId, clientSecret, scope, accessTokenEndpoint, null); + } + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, null, null); + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + this.service = serviceBuilder.build(this.apiInstance); + } + + public OAuth2AccessToken obtainAccessToken(String scope) throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken tokenResponse; + if (scope != null && !scope.trim().isEmpty()) { + tokenResponse = service.getAccessTokenClientCredentialsGrant(scope); + } else { + tokenResponse = service.getAccessTokenClientCredentialsGrant(); + } + + this.setAccessToken(tokenResponse.getAccessToken()); + + return tokenResponse; + } + + public void setToken(OAuth2AccessToken token) { + this.setToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setAccessToken(accessToken); + } + +} diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java new file mode 100644 index 00000000000..99319dc3afd --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java @@ -0,0 +1,81 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthPasswordGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + + public OAuthPasswordGrant(String clientId, String clientSecret, String accessTokenEndpoint) { + this(clientId, clientSecret, null, accessTokenEndpoint, null, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint) { + this(clientId, clientSecret, scope, accessTokenEndpoint, null, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, String refreshTokenUrl) { + this(clientId, clientSecret, scope, accessTokenEndpoint, refreshTokenUrl, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, String refreshTokenUrl, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, null, refreshTokenUrl); + + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + this.service = serviceBuilder.build(this.apiInstance); + } + + public OAuth2AccessToken obtainAccessToken(String username, String password) throws IOException, ExecutionException, InterruptedException { + return this.obtainAccessToken(username, password, null); + } + + public OAuth2AccessToken obtainAccessToken(String username, String password, String scope) throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken tokenResponse; + if (scope != null && !scope.trim().isEmpty()) { + tokenResponse = service.getAccessTokenPasswordGrant(username, password, scope); + } else { + tokenResponse = service.getAccessTokenPasswordGrant(username, password); + } + + this.setAccessToken(tokenResponse.getAccessToken()); + + return tokenResponse; + } + + public void setToken(OAuth2AccessToken token) { + this.setToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setToken(accessToken); + } + + public OAuth2AccessToken refreshToken(OAuth2AccessToken token) throws IOException, ExecutionException, InterruptedException { + return this.refreshToken(token.getRefreshToken()); + } + + public OAuth2AccessToken refreshToken(String refreshToken) throws IOException, ExecutionException, InterruptedException { + return this.service.refreshAccessToken(refreshToken); + } + +} diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/.openapi-generator/FILES b/samples/client/petstore/java/okhttp-gson-parcelableModel/.openapi-generator/FILES index 3cd17323715..e0fffde470a 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/.openapi-generator/FILES +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/.openapi-generator/FILES @@ -86,12 +86,14 @@ src/main/java/org/openapitools/client/api/StoreApi.java src/main/java/org/openapitools/client/api/UserApi.java src/main/java/org/openapitools/client/auth/ApiKeyAuth.java src/main/java/org/openapitools/client/auth/Authentication.java +src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java src/main/java/org/openapitools/client/auth/HttpBasicAuth.java src/main/java/org/openapitools/client/auth/HttpBearerAuth.java src/main/java/org/openapitools/client/auth/OAuth.java +src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java +src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java src/main/java/org/openapitools/client/auth/OAuthFlow.java -src/main/java/org/openapitools/client/auth/OAuthOkHttpClient.java -src/main/java/org/openapitools/client/auth/RetryingOAuth.java +src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java src/main/java/org/openapitools/client/model/AdditionalPropertiesAnyType.java src/main/java/org/openapitools/client/model/AdditionalPropertiesArray.java src/main/java/org/openapitools/client/model/AdditionalPropertiesBoolean.java diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/build.gradle b/samples/client/petstore/java/okhttp-gson-parcelableModel/build.gradle index 8646aedd851..d4085aba868 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/build.gradle +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/build.gradle @@ -111,7 +111,8 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.6' implementation 'io.gsonfire:gson-fire:1.8.4' implementation 'org.openapitools:jackson-databind-nullable:0.2.1' - implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + implementation group: 'com.github.scribejava', name: 'scribejava-core', version: '8.3.1' + implementation group: 'com.github.scribejava', name: 'scribejava-httpclient-okhttp', version: '8.3.1' implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' implementation 'org.threeten:threetenbp:1.4.3' implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/build.sbt b/samples/client/petstore/java/okhttp-gson-parcelableModel/build.sbt index e566d0fb4fb..522b0bdcb94 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/build.sbt +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/build.sbt @@ -15,7 +15,8 @@ lazy val root = (project in file(".")). "com.google.code.gson" % "gson" % "2.8.6", "org.apache.commons" % "commons-lang3" % "3.10", "org.openapitools" % "jackson-databind-nullable" % "0.2.1", - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", + "com.github.scribejava" % "scribejava-core" % "8.3.1", + "com.github.scribejava" % "scribejava-httpclient-okhttp" % "8.3.1", "org.threeten" % "threetenbp" % "1.4.3" % "compile", "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/pom.xml b/samples/client/petstore/java/okhttp-gson-parcelableModel/pom.xml index 3235bef8854..b57d04e8e9a 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/pom.xml +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/pom.xml @@ -239,9 +239,14 @@ <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> + <groupId>com.github.scribejava</groupId> + <artifactId>scribejava-core</artifactId> + <version>8.3.1</version> + </dependency> + <dependency> + <groupId>com.github.scribejava</groupId> + <artifactId>scribejava-httpclient-okhttp</artifactId> + <version>8.3.1</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/ApiClient.java index dfe8cf3a0c2..6db8900e8dd 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/ApiClient.java @@ -23,8 +23,6 @@ import okio.Okio; 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; @@ -51,13 +49,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.openapitools.client.auth.Authentication; -import org.openapitools.client.auth.HttpBasicAuth; -import org.openapitools.client.auth.HttpBearerAuth; -import org.openapitools.client.auth.ApiKeyAuth; -import org.openapitools.client.auth.OAuth; -import org.openapitools.client.auth.RetryingOAuth; -import org.openapitools.client.auth.OAuthFlow; +import org.openapitools.client.auth.*; public class ApiClient { @@ -138,30 +130,37 @@ public class ApiClient { } /* - * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + * Constructor for ApiClient configured with base path, client ID, secret, and additional parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map<String, String> parameters) { + this(basePath, clientId, clientSecret, null, null, parameters); + } + + /* + * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + */ + public ApiClient(String basePath, String clientId, String clientSecret, String scope, String callbackUrl, Map<String, String> parameters) { init(); if (basePath != null) { this.basePath = basePath; } - String tokenUrl = ""; - if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) { - URI uri = URI.create(getBasePath()); - tokenUrl = uri.getScheme() + ":" + - (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + - tokenUrl; - if (!URI.create(tokenUrl).isAbsolute()) { - throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); - } + initHttpClient(); + + switch(OAuthFlow.implicit) { + case accessCode: + authentications.put("petstore_auth", new OAuthAuthorizationCodeGrant(clientId, clientSecret, scope, getAuthorizationUrl(), getTokenUrl(), callbackUrl, getRefreshUrl(), parameters, this.httpClient)); + break; + case password: + authentications.put("petstore_auth", new OAuthPasswordGrant(clientId, clientSecret, scope, getTokenUrl(), getRefreshUrl(), this.httpClient)); + break; + case application: + authentications.put("petstore_auth", new OAuthClientCredentialsGrant(clientId, clientSecret, scope, getTokenUrl(), this.httpClient)); + break; + default: + throw new IllegalArgumentException("OAuth flow not implemented"); } - RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.implicit, clientSecret, parameters); - authentications.put( - "petstore_auth", - retryingOAuth - ); - initHttpClient(Collections.<Interceptor>singletonList(retryingOAuth)); + // 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")); @@ -171,6 +170,45 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + private String getTokenUrl() { + try { + return getAbsoluteUrl(""); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); + } + } + + private String getAuthorizationUrl() { + try { + return getAbsoluteUrl("http://petstore.swagger.io/api/oauth/dialog"); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 authorization URL must be an absolute URL"); + } + } + + private String getRefreshUrl() { + try { + return getAbsoluteUrl(""); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 authorization URL must be an absolute URL"); + } + } + + private String getAbsoluteUrl(String url) throws IllegalArgumentException { + if (!"".equals(url) && !URI.create(url).isAbsolute()) { + URI uri = URI.create(getBasePath()); + String absoluteUrl = uri.getScheme() + ":" + + (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + + url; + if (!URI.create(absoluteUrl).isAbsolute()) { + throw new IllegalArgumentException("Unable to obtain an absolute URL"); + } + return absoluteUrl; + } else { + return url; + } + } + private void initHttpClient() { initHttpClient(Collections.<Interceptor>emptyList()); } @@ -599,21 +637,6 @@ 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. * diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java new file mode 100644 index 00000000000..c39eb1221a8 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java @@ -0,0 +1,65 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class DefaultApi20Impl extends DefaultApi20 { + + private final String accessTokenEndpoint; + private final String authorizationBaseUrl; + private final String refreshTokenEndpoint; + + protected DefaultApi20Impl(String accessTokenEndpoint) { + this(accessTokenEndpoint, null, null); + } + + protected DefaultApi20Impl(String accessTokenEndpoint, String refreshTokenEndpoint) { + this(accessTokenEndpoint, null, refreshTokenEndpoint); + } + + protected DefaultApi20Impl(String accessTokenEndpoint, String authorizationBaseUrl, String refreshTokenEndpoint) { + this.accessTokenEndpoint = accessTokenEndpoint; + this.authorizationBaseUrl = authorizationBaseUrl; + this.refreshTokenEndpoint = refreshTokenEndpoint; + } + + @Override + public String getRefreshTokenEndpoint() { + if (this.refreshTokenEndpoint == null || this.refreshTokenEndpoint.trim().isEmpty()) { + return this.getAccessTokenEndpoint(); + } + return this.refreshTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return this.authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor<OAuth2AccessToken> getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java new file mode 100644 index 00000000000..33eddbe51f2 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java @@ -0,0 +1,106 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2Authorization; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthAuthorizationCodeGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + private Map<String, String> params; + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map<String, String> params) { + this(clientId, clientSecret, null, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, null, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map<String, String> params) { + this(clientId, clientSecret, scope, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, null, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, String refreshUrl, Map<String, String> params) { + this(clientId, clientSecret, scope, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, refreshUrl, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, String refreshUrl, Map<String, String> params, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, authorizationBaseUrl, refreshUrl); + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback(callbackUrl); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + + this.service = serviceBuilder.build(this.apiInstance); + + this.params = params; + } + + public String getAuthorizationUrl(String state) { + if (state != null && !state.trim().isEmpty()) { + return this.service.getAuthorizationUrl(state); + } else { + return this.service.getAuthorizationUrl(); + } + } + + public OAuth2Authorization extractAuthorization(String redirectLocation) { + return service.extractAuthorization(redirectLocation); + } + + public OAuth2AccessToken obtainAccessToken(OAuth2Authorization authorization, String scope) throws IOException, ExecutionException, InterruptedException { + return this.obtainAccessToken(authorization.getCode(), scope); + } + + public OAuth2AccessToken obtainAccessToken(String code, String scope) throws IOException, ExecutionException, InterruptedException { + AccessTokenRequestParams reqParams = new AccessTokenRequestParams(code); + reqParams.addExtraParameters(params); + + if (scope != null && !scope.trim().isEmpty()) { + reqParams.scope(scope); + } + + OAuth2AccessToken tokenResponse = service.getAccessToken(reqParams); + + this.setAccessToken(tokenResponse.getAccessToken()); + return tokenResponse; + } + + + public void setToken(OAuth2AccessToken token) { + this.setAccessToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setAccessToken(accessToken); + } + + public OAuth2AccessToken refreshToken(OAuth2AccessToken token, String scope) throws IOException, ExecutionException, InterruptedException { + return this.refreshToken(token.getRefreshToken(), scope); + } + + public OAuth2AccessToken refreshToken(String refreshToken, String scope) throws IOException, ExecutionException, InterruptedException { + if (scope != null && !scope.trim().isEmpty()) { + return this.service.refreshAccessToken(refreshToken, scope); + } else { + return this.service.refreshAccessToken(refreshToken); + } + } + +} diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java new file mode 100644 index 00000000000..439728c6b46 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java @@ -0,0 +1,64 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthClientCredentialsGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String accessTokenEndpoint) { + this(clientId, clientSecret, null, accessTokenEndpoint, null); + } + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint) { + this(clientId, clientSecret, scope, accessTokenEndpoint, null); + } + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, null, null); + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + this.service = serviceBuilder.build(this.apiInstance); + } + + public OAuth2AccessToken obtainAccessToken(String scope) throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken tokenResponse; + if (scope != null && !scope.trim().isEmpty()) { + tokenResponse = service.getAccessTokenClientCredentialsGrant(scope); + } else { + tokenResponse = service.getAccessTokenClientCredentialsGrant(); + } + + this.setAccessToken(tokenResponse.getAccessToken()); + + return tokenResponse; + } + + public void setToken(OAuth2AccessToken token) { + this.setToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setAccessToken(accessToken); + } + +} diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java new file mode 100644 index 00000000000..99319dc3afd --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java @@ -0,0 +1,81 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthPasswordGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + + public OAuthPasswordGrant(String clientId, String clientSecret, String accessTokenEndpoint) { + this(clientId, clientSecret, null, accessTokenEndpoint, null, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint) { + this(clientId, clientSecret, scope, accessTokenEndpoint, null, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, String refreshTokenUrl) { + this(clientId, clientSecret, scope, accessTokenEndpoint, refreshTokenUrl, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, String refreshTokenUrl, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, null, refreshTokenUrl); + + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + this.service = serviceBuilder.build(this.apiInstance); + } + + public OAuth2AccessToken obtainAccessToken(String username, String password) throws IOException, ExecutionException, InterruptedException { + return this.obtainAccessToken(username, password, null); + } + + public OAuth2AccessToken obtainAccessToken(String username, String password, String scope) throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken tokenResponse; + if (scope != null && !scope.trim().isEmpty()) { + tokenResponse = service.getAccessTokenPasswordGrant(username, password, scope); + } else { + tokenResponse = service.getAccessTokenPasswordGrant(username, password); + } + + this.setAccessToken(tokenResponse.getAccessToken()); + + return tokenResponse; + } + + public void setToken(OAuth2AccessToken token) { + this.setToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setToken(accessToken); + } + + public OAuth2AccessToken refreshToken(OAuth2AccessToken token) throws IOException, ExecutionException, InterruptedException { + return this.refreshToken(token.getRefreshToken()); + } + + public OAuth2AccessToken refreshToken(String refreshToken) throws IOException, ExecutionException, InterruptedException { + return this.service.refreshAccessToken(refreshToken); + } + +} diff --git a/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES b/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES index 3cd17323715..e0fffde470a 100644 --- a/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES +++ b/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES @@ -86,12 +86,14 @@ src/main/java/org/openapitools/client/api/StoreApi.java src/main/java/org/openapitools/client/api/UserApi.java src/main/java/org/openapitools/client/auth/ApiKeyAuth.java src/main/java/org/openapitools/client/auth/Authentication.java +src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java src/main/java/org/openapitools/client/auth/HttpBasicAuth.java src/main/java/org/openapitools/client/auth/HttpBearerAuth.java src/main/java/org/openapitools/client/auth/OAuth.java +src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java +src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java src/main/java/org/openapitools/client/auth/OAuthFlow.java -src/main/java/org/openapitools/client/auth/OAuthOkHttpClient.java -src/main/java/org/openapitools/client/auth/RetryingOAuth.java +src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java src/main/java/org/openapitools/client/model/AdditionalPropertiesAnyType.java src/main/java/org/openapitools/client/model/AdditionalPropertiesArray.java src/main/java/org/openapitools/client/model/AdditionalPropertiesBoolean.java diff --git a/samples/client/petstore/java/okhttp-gson/build.gradle b/samples/client/petstore/java/okhttp-gson/build.gradle index 10b2c272abb..0ba4a5d602d 100644 --- a/samples/client/petstore/java/okhttp-gson/build.gradle +++ b/samples/client/petstore/java/okhttp-gson/build.gradle @@ -111,7 +111,8 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.6' implementation 'io.gsonfire:gson-fire:1.8.4' implementation 'org.openapitools:jackson-databind-nullable:0.2.1' - implementation group: 'org.apache.oltu.oauth2', name: 'org.apache.oltu.oauth2.client', version: '1.0.1' + implementation group: 'com.github.scribejava', name: 'scribejava-core', version: '8.3.1' + implementation group: 'com.github.scribejava', name: 'scribejava-httpclient-okhttp', version: '8.3.1' implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' implementation 'org.threeten:threetenbp:1.4.3' implementation "jakarta.annotation:jakarta.annotation-api:$jakarta_annotation_version" diff --git a/samples/client/petstore/java/okhttp-gson/build.sbt b/samples/client/petstore/java/okhttp-gson/build.sbt index a791297fd3e..e2583967a18 100644 --- a/samples/client/petstore/java/okhttp-gson/build.sbt +++ b/samples/client/petstore/java/okhttp-gson/build.sbt @@ -15,7 +15,8 @@ lazy val root = (project in file(".")). "com.google.code.gson" % "gson" % "2.8.6", "org.apache.commons" % "commons-lang3" % "3.10", "org.openapitools" % "jackson-databind-nullable" % "0.2.1", - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1", + "com.github.scribejava" % "scribejava-core" % "8.3.1", + "com.github.scribejava" % "scribejava-httpclient-okhttp" % "8.3.1", "org.threeten" % "threetenbp" % "1.4.3" % "compile", "io.gsonfire" % "gson-fire" % "1.8.3" % "compile", "jakarta.annotation" % "jakarta.annotation-api" % "1.3.5" % "compile", diff --git a/samples/client/petstore/java/okhttp-gson/pom.xml b/samples/client/petstore/java/okhttp-gson/pom.xml index f3c9b191c95..0e9b8a8db7e 100644 --- a/samples/client/petstore/java/okhttp-gson/pom.xml +++ b/samples/client/petstore/java/okhttp-gson/pom.xml @@ -239,9 +239,14 @@ <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> + <groupId>com.github.scribejava</groupId> + <artifactId>scribejava-core</artifactId> + <version>8.3.1</version> + </dependency> + <dependency> + <groupId>com.github.scribejava</groupId> + <artifactId>scribejava-httpclient-okhttp</artifactId> + <version>8.3.1</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/ApiClient.java index dfe8cf3a0c2..6db8900e8dd 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/ApiClient.java @@ -23,8 +23,6 @@ import okio.Okio; 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; @@ -51,13 +49,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.openapitools.client.auth.Authentication; -import org.openapitools.client.auth.HttpBasicAuth; -import org.openapitools.client.auth.HttpBearerAuth; -import org.openapitools.client.auth.ApiKeyAuth; -import org.openapitools.client.auth.OAuth; -import org.openapitools.client.auth.RetryingOAuth; -import org.openapitools.client.auth.OAuthFlow; +import org.openapitools.client.auth.*; public class ApiClient { @@ -138,30 +130,37 @@ public class ApiClient { } /* - * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + * Constructor for ApiClient configured with base path, client ID, secret, and additional parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map<String, String> parameters) { + this(basePath, clientId, clientSecret, null, null, parameters); + } + + /* + * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters + */ + public ApiClient(String basePath, String clientId, String clientSecret, String scope, String callbackUrl, Map<String, String> parameters) { init(); if (basePath != null) { this.basePath = basePath; } - String tokenUrl = ""; - if (!"".equals(tokenUrl) && !URI.create(tokenUrl).isAbsolute()) { - URI uri = URI.create(getBasePath()); - tokenUrl = uri.getScheme() + ":" + - (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + - tokenUrl; - if (!URI.create(tokenUrl).isAbsolute()) { - throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); - } + initHttpClient(); + + switch(OAuthFlow.implicit) { + case accessCode: + authentications.put("petstore_auth", new OAuthAuthorizationCodeGrant(clientId, clientSecret, scope, getAuthorizationUrl(), getTokenUrl(), callbackUrl, getRefreshUrl(), parameters, this.httpClient)); + break; + case password: + authentications.put("petstore_auth", new OAuthPasswordGrant(clientId, clientSecret, scope, getTokenUrl(), getRefreshUrl(), this.httpClient)); + break; + case application: + authentications.put("petstore_auth", new OAuthClientCredentialsGrant(clientId, clientSecret, scope, getTokenUrl(), this.httpClient)); + break; + default: + throw new IllegalArgumentException("OAuth flow not implemented"); } - RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.implicit, clientSecret, parameters); - authentications.put( - "petstore_auth", - retryingOAuth - ); - initHttpClient(Collections.<Interceptor>singletonList(retryingOAuth)); + // 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")); @@ -171,6 +170,45 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + private String getTokenUrl() { + try { + return getAbsoluteUrl(""); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 token URL must be an absolute URL"); + } + } + + private String getAuthorizationUrl() { + try { + return getAbsoluteUrl("http://petstore.swagger.io/api/oauth/dialog"); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 authorization URL must be an absolute URL"); + } + } + + private String getRefreshUrl() { + try { + return getAbsoluteUrl(""); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("OAuth2 authorization URL must be an absolute URL"); + } + } + + private String getAbsoluteUrl(String url) throws IllegalArgumentException { + if (!"".equals(url) && !URI.create(url).isAbsolute()) { + URI uri = URI.create(getBasePath()); + String absoluteUrl = uri.getScheme() + ":" + + (uri.getAuthority() != null ? "//" + uri.getAuthority() : "") + + url; + if (!URI.create(absoluteUrl).isAbsolute()) { + throw new IllegalArgumentException("Unable to obtain an absolute URL"); + } + return absoluteUrl; + } else { + return url; + } + } + private void initHttpClient() { initHttpClient(Collections.<Interceptor>emptyList()); } @@ -599,21 +637,6 @@ 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. * diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java new file mode 100644 index 00000000000..c39eb1221a8 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java @@ -0,0 +1,65 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.api.DefaultApi20; +import com.github.scribejava.core.extractors.OAuth2AccessTokenJsonExtractor; +import com.github.scribejava.core.extractors.TokenExtractor; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignature; +import com.github.scribejava.core.oauth2.bearersignature.BearerSignatureURIQueryParameter; +import com.github.scribejava.core.oauth2.clientauthentication.ClientAuthentication; +import com.github.scribejava.core.oauth2.clientauthentication.RequestBodyAuthenticationScheme; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class DefaultApi20Impl extends DefaultApi20 { + + private final String accessTokenEndpoint; + private final String authorizationBaseUrl; + private final String refreshTokenEndpoint; + + protected DefaultApi20Impl(String accessTokenEndpoint) { + this(accessTokenEndpoint, null, null); + } + + protected DefaultApi20Impl(String accessTokenEndpoint, String refreshTokenEndpoint) { + this(accessTokenEndpoint, null, refreshTokenEndpoint); + } + + protected DefaultApi20Impl(String accessTokenEndpoint, String authorizationBaseUrl, String refreshTokenEndpoint) { + this.accessTokenEndpoint = accessTokenEndpoint; + this.authorizationBaseUrl = authorizationBaseUrl; + this.refreshTokenEndpoint = refreshTokenEndpoint; + } + + @Override + public String getRefreshTokenEndpoint() { + if (this.refreshTokenEndpoint == null || this.refreshTokenEndpoint.trim().isEmpty()) { + return this.getAccessTokenEndpoint(); + } + return this.refreshTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return this.authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor<OAuth2AccessToken> getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java new file mode 100644 index 00000000000..33eddbe51f2 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java @@ -0,0 +1,106 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2Authorization; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthAuthorizationCodeGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + private Map<String, String> params; + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map<String, String> params) { + this(clientId, clientSecret, null, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, null, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map<String, String> params) { + this(clientId, clientSecret, scope, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, null, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, String refreshUrl, Map<String, String> params) { + this(clientId, clientSecret, scope, authorizationBaseUrl, accessTokenEndpoint, callbackUrl, refreshUrl, params, null); + } + + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String scope, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, String refreshUrl, Map<String, String> params, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, authorizationBaseUrl, refreshUrl); + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .callback(callbackUrl); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + + this.service = serviceBuilder.build(this.apiInstance); + + this.params = params; + } + + public String getAuthorizationUrl(String state) { + if (state != null && !state.trim().isEmpty()) { + return this.service.getAuthorizationUrl(state); + } else { + return this.service.getAuthorizationUrl(); + } + } + + public OAuth2Authorization extractAuthorization(String redirectLocation) { + return service.extractAuthorization(redirectLocation); + } + + public OAuth2AccessToken obtainAccessToken(OAuth2Authorization authorization, String scope) throws IOException, ExecutionException, InterruptedException { + return this.obtainAccessToken(authorization.getCode(), scope); + } + + public OAuth2AccessToken obtainAccessToken(String code, String scope) throws IOException, ExecutionException, InterruptedException { + AccessTokenRequestParams reqParams = new AccessTokenRequestParams(code); + reqParams.addExtraParameters(params); + + if (scope != null && !scope.trim().isEmpty()) { + reqParams.scope(scope); + } + + OAuth2AccessToken tokenResponse = service.getAccessToken(reqParams); + + this.setAccessToken(tokenResponse.getAccessToken()); + return tokenResponse; + } + + + public void setToken(OAuth2AccessToken token) { + this.setAccessToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setAccessToken(accessToken); + } + + public OAuth2AccessToken refreshToken(OAuth2AccessToken token, String scope) throws IOException, ExecutionException, InterruptedException { + return this.refreshToken(token.getRefreshToken(), scope); + } + + public OAuth2AccessToken refreshToken(String refreshToken, String scope) throws IOException, ExecutionException, InterruptedException { + if (scope != null && !scope.trim().isEmpty()) { + return this.service.refreshAccessToken(refreshToken, scope); + } else { + return this.service.refreshAccessToken(refreshToken); + } + } + +} diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java new file mode 100644 index 00000000000..439728c6b46 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java @@ -0,0 +1,64 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthClientCredentialsGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String accessTokenEndpoint) { + this(clientId, clientSecret, null, accessTokenEndpoint, null); + } + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint) { + this(clientId, clientSecret, scope, accessTokenEndpoint, null); + } + + public OAuthClientCredentialsGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, null, null); + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + this.service = serviceBuilder.build(this.apiInstance); + } + + public OAuth2AccessToken obtainAccessToken(String scope) throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken tokenResponse; + if (scope != null && !scope.trim().isEmpty()) { + tokenResponse = service.getAccessTokenClientCredentialsGrant(scope); + } else { + tokenResponse = service.getAccessTokenClientCredentialsGrant(); + } + + this.setAccessToken(tokenResponse.getAccessToken()); + + return tokenResponse; + } + + public void setToken(OAuth2AccessToken token) { + this.setToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setAccessToken(accessToken); + } + +} diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java new file mode 100644 index 00000000000..99319dc3afd --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java @@ -0,0 +1,81 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import com.github.scribejava.httpclient.okhttp.OkHttpHttpClient; +import okhttp3.OkHttpClient; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OAuthPasswordGrant extends OAuth { + private DefaultApi20Impl apiInstance; + private OAuth20Service service; + + public OAuthPasswordGrant(String clientId, String clientSecret, String accessTokenEndpoint) { + this(clientId, clientSecret, null, accessTokenEndpoint, null, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint) { + this(clientId, clientSecret, scope, accessTokenEndpoint, null, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, String refreshTokenUrl) { + this(clientId, clientSecret, scope, accessTokenEndpoint, refreshTokenUrl, null); + } + + public OAuthPasswordGrant(String clientId, String clientSecret, String scope, String accessTokenEndpoint, String refreshTokenUrl, OkHttpClient httpClient) { + this.apiInstance = new DefaultApi20Impl(accessTokenEndpoint, null, refreshTokenUrl); + + ServiceBuilder serviceBuilder = new ServiceBuilder(clientId) + .apiSecret(clientSecret); + + if (scope != null && !scope.trim().isEmpty()) { + serviceBuilder.defaultScope(scope); + } + + if (httpClient != null) { + serviceBuilder.httpClient(new OkHttpHttpClient(httpClient)); + } else { + serviceBuilder.httpClient(new OkHttpHttpClient(new OkHttpClient())); + } + + this.service = serviceBuilder.build(this.apiInstance); + } + + public OAuth2AccessToken obtainAccessToken(String username, String password) throws IOException, ExecutionException, InterruptedException { + return this.obtainAccessToken(username, password, null); + } + + public OAuth2AccessToken obtainAccessToken(String username, String password, String scope) throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken tokenResponse; + if (scope != null && !scope.trim().isEmpty()) { + tokenResponse = service.getAccessTokenPasswordGrant(username, password, scope); + } else { + tokenResponse = service.getAccessTokenPasswordGrant(username, password); + } + + this.setAccessToken(tokenResponse.getAccessToken()); + + return tokenResponse; + } + + public void setToken(OAuth2AccessToken token) { + this.setToken(token.getAccessToken()); + } + + public void setToken(String accessToken) { + this.setToken(accessToken); + } + + public OAuth2AccessToken refreshToken(OAuth2AccessToken token) throws IOException, ExecutionException, InterruptedException { + return this.refreshToken(token.getRefreshToken()); + } + + public OAuth2AccessToken refreshToken(String refreshToken) throws IOException, ExecutionException, InterruptedException { + return this.service.refreshAccessToken(refreshToken); + } + +} -- GitLab From cbf3c766627899dba51ee96288cce5d8409f1602 Mon Sep 17 00:00:00 2001 From: Mauro Valota <maurovalota@fattureincloud.it> Date: Fri, 29 Oct 2021 18:02:28 +0200 Subject: [PATCH 3/7] cleaned code --- .../libraries/okhttp-gson/ApiClient.mustache | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache index a54ee35634f..f092be90847 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache @@ -164,7 +164,6 @@ public class ApiClient { {{#hasOAuthMethods}} initHttpClient(); - {{^java8}} switch(OAuthFlow.{{flow}}) { case accessCode: authentications.put("{{name}}", new OAuthAuthorizationCodeGrant(clientId, clientSecret, scope, getAuthorizationUrl(), getTokenUrl(), callbackUrl, getRefreshUrl(), parameters, this.httpClient)); @@ -178,22 +177,6 @@ public class ApiClient { default: throw new IllegalArgumentException("OAuth flow not implemented"); } - {{/java8}} - {{#java8}} - switch(OAuthFlow.{{flow}}) { - case accessCode: - authentications.put("{{name}}", new OAuthAuthorizationCodeGrant(clientId, clientSecret, Optional.of(scope), getAuthorizationUrl(), getTokenUrl(), callbackUrl, getRefreshUrl(), parameters, this.httpClient)); - break; - case password: - authentications.put("{{name}}", new OAuthPasswordGrant(clientId, clientSecret, scope, getTokenUrl(), getRefreshUrl(), this.httpClient)); - break; - case application: - authentications.put("{{name}}", new OAuthClientCredentialsGrant(clientId, clientSecret, scope, getTokenUrl(), this.httpClient)); - break; - default: - throw new IllegalArgumentException("OAuth flow not implemented"); - } - {{/java8}} {{/hasOAuthMethods}} // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} -- GitLab From fad17d50ddd2fe27ab98dcbfb0b3e7db00a1173c Mon Sep 17 00:00:00 2001 From: Mauro Valota <maurovalota@fattureincloud.it> Date: Sat, 30 Oct 2021 10:27:28 +0200 Subject: [PATCH 4/7] reintroduced executeStream method --- .../libraries/okhttp-gson/ApiClient.mustache | 18 ++++++++++++++++++ .../org/openapitools/client/ApiClient.java | 16 ++++++++++++++++ .../org/openapitools/client/ApiClient.java | 1 + .../org/openapitools/client/ApiClient.java | 1 + .../org/openapitools/client/ApiClient.java | 1 + 5 files changed, 37 insertions(+) diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache index f092be90847..379e9f771b0 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache @@ -1142,6 +1142,24 @@ public class ApiClient { } } + {{#supportStreaming}} + public InputStream executeStream(Call call, Type returnType) throws ApiException { + try { + Response response = call.execute(); + if (!response.isSuccessful()) { + throw new ApiException(response.code(), response.message()); + } + if (response.body() == null) { + return null; + } + return response.body().byteStream(); + } catch (IOException e) { + throw new ApiException(e); + } + } + + {{/supportStreaming}} + /** * {@link #executeAsync(Call, Type, ApiCallback)} * diff --git a/samples/client/others/java/okhttp-gson-streaming/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/others/java/okhttp-gson-streaming/src/main/java/org/openapitools/client/ApiClient.java index 412081ae259..eb49bf3d41c 100644 --- a/samples/client/others/java/okhttp-gson-streaming/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/others/java/okhttp-gson-streaming/src/main/java/org/openapitools/client/ApiClient.java @@ -923,6 +923,22 @@ public class ApiClient { } } + public InputStream executeStream(Call call, Type returnType) throws ApiException { + try { + Response response = call.execute(); + if (!response.isSuccessful()) { + throw new ApiException(response.code(), response.message()); + } + if (response.body() == null) { + return null; + } + return response.body().byteStream(); + } catch (IOException e) { + throw new ApiException(e); + } + } + + /** * {@link #executeAsync(Call, Type, ApiCallback)} * diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/ApiClient.java index 13f09144b6a..898c6586a8e 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/ApiClient.java @@ -1037,6 +1037,7 @@ public class ApiClient { } } + /** * {@link #executeAsync(Call, Type, ApiCallback)} * diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/ApiClient.java index 6db8900e8dd..f9b2ab14773 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/ApiClient.java @@ -1038,6 +1038,7 @@ public class ApiClient { } } + /** * {@link #executeAsync(Call, Type, ApiCallback)} * diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/ApiClient.java index 6db8900e8dd..f9b2ab14773 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/ApiClient.java @@ -1038,6 +1038,7 @@ public class ApiClient { } } + /** * {@link #executeAsync(Call, Type, ApiCallback)} * -- GitLab From 9598a13c63f45428003e83e5622b9031a20773ea Mon Sep 17 00:00:00 2001 From: Mauro Valota <maurovalota@fattureincloud.it> Date: Tue, 2 Nov 2021 10:15:49 +0100 Subject: [PATCH 5/7] fixed test --- .../client/auth/OAuthOkHttpClient.java | 68 ------- .../client/auth/RetryingOAuth.java | 179 ------------------ .../openapitools/client/api/PetApiTest.java | 4 - .../client/auth/RetryingOAuthTest.java | 112 ----------- 4 files changed, 363 deletions(-) delete mode 100644 samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthOkHttpClient.java delete mode 100644 samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/RetryingOAuth.java delete mode 100644 samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/RetryingOAuthTest.java diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthOkHttpClient.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthOkHttpClient.java deleted file mode 100644 index 1c8ac2dc0cc..00000000000 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthOkHttpClient.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.openapitools.client.auth; - -import okhttp3.OkHttpClient; -import okhttp3.MediaType; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.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(request.getBody(), mediaType) : 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 - } -} diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/RetryingOAuth.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/RetryingOAuth.java deleted file mode 100644 index cb79b34ca87..00000000000 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/RetryingOAuth.java +++ /dev/null @@ -1,179 +0,0 @@ -package org.openapitools.client.auth; - -import org.openapitools.client.Pair; - -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.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; -import java.util.List; - -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); - } - - /** - @param tokenUrl The token URL to be used for this OAuth2 flow. - Applicable to the following OAuth2 flows: "password", "clientCredentials" and "authorizationCode". - The value must be an absolute URL. - @param clientId The OAuth2 client ID for the "clientCredentials" flow. - @param clientSecret The OAuth2 client secret for the "clientCredentials" flow. - */ - public RetryingOAuth( - String tokenUrl, - String clientId, - OAuthFlow flow, - String clientSecret, - Map<String, String> parameters - ) { - this(OAuthClientRequest.tokenLocation(tokenUrl) - .setClientId(clientId) - .setClientSecret(clientSecret)); - setFlow(flow); - if (parameters != null) { - for (String paramName : parameters.keySet()) { - tokenRequestBuilder.setParameter(paramName, parameters.get(paramName)); - } - } - } - - public void setFlow(OAuthFlow flow) { - switch(flow) { - case accessCode: - tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); - break; - case implicit: - tokenRequestBuilder.setGrantType(GrantType.IMPLICIT); - break; - case password: - tokenRequestBuilder.setGrantType(GrantType.PASSWORD); - break; - case application: - tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); - break; - default: - break; - } - } - - @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.url().toString()). - 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()); - } - } catch (OAuthSystemException | OAuthProblemException e) { - throw new IOException(e); - } - } - return getAccessToken() == null || !getAccessToken().equals(requestAccessToken); - } - - public TokenRequestBuilder getTokenRequestBuilder() { - return tokenRequestBuilder; - } - - public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { - this.tokenRequestBuilder = tokenRequestBuilder; - } - - // Applying authorization to parameters is performed in the retryingIntercept method - @Override - public void applyToParams(List<Pair> queryParams, Map<String, String> headerParams, Map<String, String> cookieParams) { - // No implementation necessary - } -} diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/api/PetApiTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/api/PetApiTest.java index f65184b608c..3b918b497ba 100644 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/api/PetApiTest.java +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/api/PetApiTest.java @@ -34,8 +34,6 @@ import java.util.concurrent.ThreadLocalRandom; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.junit.*; @@ -47,7 +45,6 @@ import static org.junit.Assert.*; public class PetApiTest { private PetApi api = new PetApi(); - private final Logger LOG = LoggerFactory.getLogger(PetApiTest.class); // In the circle.yml file, /etc/host is configured with an entry to resolve petstore.swagger.io to 127.0.0.1 private static String basePath = "http://petstore.swagger.io:80/v2"; @@ -368,7 +365,6 @@ public class PetApiTest { fetched = api.getPetById(fetched.getId()); fail("expected an error"); } catch (ApiException e) { - LOG.info("Code: {}. Message: {}", e.getCode(), e.getMessage()); assertEquals(404, e.getCode()); } } diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/RetryingOAuthTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/RetryingOAuthTest.java deleted file mode 100644 index dca9b7c69ea..00000000000 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/RetryingOAuthTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.openapitools.client.auth; - -import okhttp3.Interceptor.Chain; -import okhttp3.*; -import okhttp3.Response.Builder; -import org.apache.commons.lang3.reflect.FieldUtils; -import org.apache.oltu.oauth2.client.OAuthClient; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest; -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.junit.Before; -import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.util.Collections; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class RetryingOAuthTest { - - private RetryingOAuth oauth; - - @Before - public void setUp() throws Exception { - oauth = new RetryingOAuth("_clientId", "_clientSecret", OAuthFlow.accessCode, - "https://token.example.com", Collections.<String, String>emptyMap()); - oauth.setAccessToken("expired-access-token"); - FieldUtils.writeField(oauth, "oAuthClient", mockOAuthClient(), true); - } - - @Test - public void testSingleRequestUnauthorized() throws Exception { - Response response = oauth.intercept(mockChain()); - assertEquals(HttpURLConnection.HTTP_OK, response.code()); - } - - @Test - public void testTwoConcurrentRequestsUnauthorized() throws Exception { - - Callable<Response> callable = new Callable<Response>() { - @Override - public Response call() throws Exception { - return oauth.intercept(mockChain()); - } - }; - ExecutorService executor = Executors.newFixedThreadPool(2); - try { - Future<Response> response1 = executor.submit(callable); - Future<Response> response2 = executor.submit(callable); - - assertEquals(HttpURLConnection.HTTP_OK, response1.get().code()); - assertEquals(HttpURLConnection.HTTP_OK, response2.get().code()); - } finally { - executor.shutdown(); - } - } - - private OAuthClient mockOAuthClient() throws OAuthProblemException, OAuthSystemException { - OAuthJSONAccessTokenResponse response = mock(OAuthJSONAccessTokenResponse.class); - when(response.getAccessToken()).thenAnswer(new Answer<String>() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - // sleep ensures that the bug is triggered. - Thread.sleep(1000); - return "new-access-token"; - } - }); - - OAuthClient client = mock(OAuthClient.class); - when(client.accessToken(any(OAuthClientRequest.class))).thenReturn(response); - return client; - } - - private Chain mockChain() throws IOException { - Chain chain = mock(Chain.class); - - final Request request = new Request.Builder() - .url("https://api.example.com") - .build(); - when(chain.request()).thenReturn(request); - - when(chain.proceed(any(Request.class))).thenAnswer(new Answer<Response>() { - @Override - public Response answer(InvocationOnMock inv) { - Request r = inv.getArgument(0); - int responseCode = "Bearer new-access-token".equals(r.header("Authorization")) - ? HttpURLConnection.HTTP_OK - : HttpURLConnection.HTTP_UNAUTHORIZED; - return new Builder() - .protocol(Protocol.HTTP_1_0) - .message("sup") - .request(request) - .body(ResponseBody.create(new byte[0], MediaType.get("application/test"))) - .code(responseCode) - .build(); - } - }); - - return chain; - } -} -- GitLab From 873b21aaad5dcadcf517fa495b73e686a087b954 Mon Sep 17 00:00:00 2001 From: Mauro Valota <maurovalota@fattureincloud.it> Date: Tue, 2 Nov 2021 10:56:30 +0100 Subject: [PATCH 6/7] adds new oauth classes tests --- .../auth/OAuthAuthorizationCodeGrantTest.java | 95 +++++++++++++++++++ .../auth/OAuthClientCredentialsGrantTest.java | 73 ++++++++++++++ .../client/auth/OAuthPasswordGrantTest.java | 75 +++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrantTest.java create mode 100644 samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthClientCredentialsGrantTest.java create mode 100644 samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthPasswordGrantTest.java diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrantTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrantTest.java new file mode 100644 index 00000000000..38b8d98be6f --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrantTest.java @@ -0,0 +1,95 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.model.OAuth2Authorization; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.junit.Before; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.openapitools.client.Pair; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class OAuthAuthorizationCodeGrantTest { + + private OAuthAuthorizationCodeGrant oauth; + + @Before + public void setUp() throws Exception { + oauth = new OAuthAuthorizationCodeGrant("_clientId", "_clientSecret", "https://token.example.com", + "https://auth.example.com", "http://localhost:8080", Collections.<String, String>emptyMap()); + oauth.setAccessToken("expired-access-token"); + FieldUtils.writeField(oauth, "service", mockOAuthService(), true); + } + + @Test + public void testApplyToParams() throws IOException, ExecutionException, InterruptedException { + List<Pair> queryParams = new ArrayList<Pair>(); + Map<String, String> headerParams = new HashMap<String, String>(); + Map<String, String> cookieParams = new HashMap<String, String>(); + + oauth.applyToParams(queryParams, headerParams, cookieParams); + + // no changes to query or cookie parameters + assertEquals(0, queryParams.size()); + assertEquals(0, cookieParams.size()); + assertEquals(1, headerParams.size()); + String expected = "Bearer expired-access-token"; + assertEquals(expected, headerParams.get("Authorization")); + + // let's simulate a new access token req + // first, build the authorization url + String state = "fake_state"; + String url = oauth.getAuthorizationUrl(state); + assertEquals("https://auth.example.com?response_type=code&client_id=_clientId&redirect_uri=http%3A%2F%2Flocalhost:8080&scope=scope&state=" + state, url); + + // for the test purpose, skipping the redirect step and simulating the callback + OAuth2Authorization authorization = oauth.extractAuthorization("http://localhost:8080?code=obtained_code&state=" + state); + String authCode = authorization.getCode(); + assertEquals(state, authorization.getState()); + assertEquals("obtained_code", authCode); + + // then the access token request + oauth.obtainAccessToken(authCode, "scope"); + oauth.applyToParams(queryParams, headerParams, cookieParams); + assertEquals(0, queryParams.size()); + assertEquals(0, cookieParams.size()); + assertEquals(1, headerParams.size()); + expected = "Bearer new-access-token"; + assertEquals(expected, headerParams.get("Authorization")); + } + + private OAuth20Service mockOAuthService() throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken response = mock(OAuth2AccessToken.class); + when(response.getAccessToken()).thenAnswer(new Answer<String>() { + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + // sleep ensures that the bug is triggered. + Thread.sleep(1000); + return "new-access-token"; + } + }); + + OAuth20Service service = mock(OAuth20Service.class); + when(service.getAuthorizationUrl(eq("fake_state"))) + .thenReturn("https://auth.example.com?response_type=code&client_id=_clientId&redirect_uri=http%3A%2F%2Flocalhost:8080&scope=scope&state=fake_state"); + OAuth2Authorization auth = new OAuth2Authorization(); + auth.setCode("obtained_code"); + auth.setState("fake_state"); + when(service.extractAuthorization(eq("http://localhost:8080?code=obtained_code&state=fake_state"))) + .thenReturn(auth); + when(service.getAccessToken(any(AccessTokenRequestParams.class))).thenReturn(response); + return service; + } +} diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthClientCredentialsGrantTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthClientCredentialsGrantTest.java new file mode 100644 index 00000000000..282c1420ebf --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthClientCredentialsGrantTest.java @@ -0,0 +1,73 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.AccessTokenRequestParams; +import com.github.scribejava.core.oauth.OAuth20Service; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.junit.Before; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.openapitools.client.Pair; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class OAuthClientCredentialsGrantTest { + + private OAuthClientCredentialsGrant oauth; + + @Before + public void setUp() throws Exception { + oauth = new OAuthClientCredentialsGrant("_clientId", "_clientSecret", "https://token.example.com"); + oauth.setAccessToken("expired-access-token"); + FieldUtils.writeField(oauth, "service", mockOAuthService(), true); + } + + @Test + public void testApplyToParams() throws IOException, ExecutionException, InterruptedException { + List<Pair> queryParams = new ArrayList<Pair>(); + Map<String, String> headerParams = new HashMap<String, String>(); + Map<String, String> cookieParams = new HashMap<String, String>(); + + oauth.applyToParams(queryParams, headerParams, cookieParams); + + // no changes to query or cookie parameters + assertEquals(0, queryParams.size()); + assertEquals(0, cookieParams.size()); + assertEquals(1, headerParams.size()); + String expected = "Bearer expired-access-token"; + assertEquals(expected, headerParams.get("Authorization")); + + // let's try to get a new access token + oauth.obtainAccessToken("scope"); + oauth.applyToParams(queryParams, headerParams, cookieParams); + assertEquals(0, queryParams.size()); + assertEquals(0, cookieParams.size()); + assertEquals(1, headerParams.size()); + expected = "Bearer new-access-token"; + assertEquals(expected, headerParams.get("Authorization")); + } + + private OAuth20Service mockOAuthService() throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken response = mock(OAuth2AccessToken.class); + when(response.getAccessToken()).thenAnswer(new Answer<String>() { + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + // sleep ensures that the bug is triggered. + Thread.sleep(1000); + return "new-access-token"; + } + }); + + OAuth20Service service = mock(OAuth20Service.class); + when(service.getAccessTokenClientCredentialsGrant(eq("scope"))).thenReturn(response); + return service; + } +} diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthPasswordGrantTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthPasswordGrantTest.java new file mode 100644 index 00000000000..0d15949b71c --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthPasswordGrantTest.java @@ -0,0 +1,75 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.junit.Before; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.openapitools.client.Pair; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class OAuthPasswordGrantTest { + + private OAuthPasswordGrant oauth; + + @Before + public void setUp() throws Exception { + oauth = new OAuthPasswordGrant("_clientId", "_clientSecret", "https://token.example.com"); + oauth.setAccessToken("expired-access-token"); + FieldUtils.writeField(oauth, "service", mockOAuthService(), true); + } + + @Test + public void testApplyToParams() throws IOException, ExecutionException, InterruptedException { + List<Pair> queryParams = new ArrayList<Pair>(); + Map<String, String> headerParams = new HashMap<String, String>(); + Map<String, String> cookieParams = new HashMap<String, String>(); + + oauth.applyToParams(queryParams, headerParams, cookieParams); + + // no changes to query or cookie parameters + assertEquals(0, queryParams.size()); + assertEquals(0, cookieParams.size()); + assertEquals(1, headerParams.size()); + String expected = "Bearer expired-access-token"; + assertEquals(expected, headerParams.get("Authorization")); + + // let's try to get a new access token + oauth.obtainAccessToken("_username", "_password", "scope"); + oauth.applyToParams(queryParams, headerParams, cookieParams); + assertEquals(0, queryParams.size()); + assertEquals(0, cookieParams.size()); + assertEquals(1, headerParams.size()); + expected = "Bearer new-access-token"; + assertEquals(expected, headerParams.get("Authorization")); + } + + private OAuth20Service mockOAuthService() throws IOException, ExecutionException, InterruptedException { + OAuth2AccessToken response = mock(OAuth2AccessToken.class); + when(response.getAccessToken()).thenAnswer(new Answer<String>() { + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + // sleep ensures that the bug is triggered. + Thread.sleep(1000); + return "new-access-token"; + } + }); + + OAuth20Service service = mock(OAuth20Service.class); + when(service.getAccessTokenPasswordGrant(eq("_username"), eq("_password"), eq("scope"))).thenReturn(response); + return service; + } +} -- GitLab From 15bd22f5c438775bf87737af6f7e42a2b41f7a75 Mon Sep 17 00:00:00 2001 From: Mauro Valota <maurovalota@fattureincloud.it> Date: Tue, 2 Nov 2021 11:24:10 +0100 Subject: [PATCH 7/7] removed tabs --- .../src/main/resources/Java/libraries/okhttp-gson/pom.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pom.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pom.mustache index 8d64ffccf13..68521a6133b 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pom.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pom.mustache @@ -364,7 +364,7 @@ <jakarta.el-version>3.0.3</jakarta.el-version> {{/performBeanValidation}} {{#useBeanValidation}} - <beanvalidation-version>2.0.2</beanvalidation-version> + <beanvalidation-version>2.0.2</beanvalidation-version> {{/useBeanValidation}} <junit-version>4.13.2</junit-version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> -- GitLab