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 f675c9a9c3f1..565d2740bd4f 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 @@ -635,9 +635,11 @@ public void processOpts() { // has OAuth defined 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())) || OKHTTP_GSON_NEXTGEN.equals(getLibrary())) { - supportingFiles.add(new SupportingFile("auth/OAuthOkHttpClient.mustache", authFolder, "OAuthOkHttpClient.java")); - supportingFiles.add(new SupportingFile("auth/RetryingOAuth.mustache", authFolder, "RetryingOAuth.java")); + if ((OKHTTP_GSON.equals(getLibrary()) || StringUtils.isEmpty(getLibrary()) || OKHTTP_GSON_NEXTGEN.equals(getLibrary()))) { + 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 421b7782ebef..25bb708ab35d 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 @@ -28,10 +28,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; @@ -63,15 +59,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.*; /** *

ApiClient class.

@@ -173,36 +161,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 - * - * @param basePath base path - * @param clientId client ID - * @param clientSecret client secret - * @param parameters a {@link java.util.Map} of parameters + * * Constructor for ApiClient configured with base path, client ID, secret, and additional parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map 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 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(); + + 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"); } - RetryingOAuth retryingOAuth = new RetryingOAuth(tokenUrl, clientId, OAuthFlow.{{flow}}, clientSecret, parameters); - authentications.put( - "{{name}}", - retryingOAuth - ); - initHttpClient(Collections.singletonList(retryingOAuth)); {{/hasOAuthMethods}} // Setup authentications (key: authentication name, value: authentication).{{#authMethods}}{{#isBasic}}{{#isBasicBasic}} authentications.put("{{name}}", new HttpBasicAuth());{{/isBasicBasic}}{{^isBasicBasic}} @@ -213,6 +202,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}} @@ -724,23 +754,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. * 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 000000000000..1cf8f28a6ac0 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/DefaultApi20Impl.mustache @@ -0,0 +1,65 @@ +{{#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 getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} +{{/hasOAuthMethods}} \ No newline at end of file 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 000000000000..4a1a86796e56 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthAuthorizationCodeGrant.mustache @@ -0,0 +1,105 @@ +{{#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 params; + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map 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 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 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 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}} \ No newline at end of file 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 000000000000..63dedbb0df9c --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthClientCredentialsGrant.mustache @@ -0,0 +1,64 @@ +{{#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}} \ No newline at end of file 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 cb0e82505507..000000000000 --- 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 execute(OAuthClientRequest request, Map headers, - String requestMethod, Class responseClass) - throws OAuthSystemException, OAuthProblemException { - - MediaType mediaType = MediaType.parse("application/json"); - Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri()); - - if(headers != null) { - for (Entry 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 000000000000..4c503f8bfab4 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/OAuthPasswordGrant.mustache @@ -0,0 +1,80 @@ +{{#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}} \ No newline at end of file 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 137e266b5a29..000000000000 --- a/modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/auth/RetryingOAuth.mustache +++ /dev/null @@ -1,184 +0,0 @@ -{{#hasOAuthMethods}} -package {{invokerPackage}}.auth; - -import {{invokerPackage}}.ApiException; -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.net.URI; -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 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 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 queryParams, Map headerParams, Map cookieParams, - String payload, String method, URI uri) throws ApiException { - // 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 c97cb873e97b..266b69099d0d 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 @@ -120,7 +120,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 5e0c74c55c05..4ea4b7cf72cc 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.2", {{/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 94c057b1424a..7ca246bd2aa0 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 @@ -289,9 +289,14 @@ {{#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}} 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 e5613d745cf9..71b63ea25c26 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 void testIgnoreFileProcessing() throws IOException { List files = generator.opts(clientOptInput).generate(); - Assert.assertEquals(files.size(), 42); + Assert.assertEquals(files.size(), 44); // Check expected generated files // api sanity check 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 f2fca9d7ea3b..655676154563 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 @@ -50,10 +50,7 @@ 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.*; /** *

ApiClient class.

@@ -571,7 +568,6 @@ public ApiClient setWriteTimeout(int writeTimeout) { return this; } - /** * Format the given parameter object into string. * 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 5597480c76d3..de4fb2cb4740 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 3344fafe8de8..581c54eaa4b9 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.gradle +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/build.gradle @@ -113,7 +113,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 7de5adcd583f..394b626e2d33 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.2", - "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 9e8777894cea..03501cfe787a 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/pom.xml +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/pom.xml @@ -281,9 +281,14 @@ ${gson-fire-version}
- 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.apache.commons 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 ddd9a420bb65..1c099ae441da 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 @@ -30,8 +30,6 @@ 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; @@ -58,13 +56,7 @@ 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.*; /** *

ApiClient class.

@@ -161,35 +153,36 @@ public ApiClient(String clientId, String clientSecret, Map param } /** - * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters - * - * @param basePath base path - * @param clientId client ID - * @param clientSecret client secret - * @param parameters a {@link java.util.Map} of parameters + * * Constructor for ApiClient configured with base path, client ID, secret, and additional parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map 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 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.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")); @@ -199,6 +192,45 @@ public ApiClient(String basePath, String clientId, String clientSecret, MapemptyList()); } @@ -670,21 +702,6 @@ public ApiClient setWriteTimeout(int writeTimeout) { 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 000000000000..5de9aa949ff0 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java @@ -0,0 +1,63 @@ +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 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 000000000000..eec4d8350f0b --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java @@ -0,0 +1,103 @@ +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 params; + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map 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 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 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 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 000000000000..5c319ef0a5f6 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java @@ -0,0 +1,62 @@ +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 000000000000..f4f8b398f86d --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java @@ -0,0 +1,78 @@ +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 3cd173237152..e0fffde470ac 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 2f3893812421..299bf78c6576 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/build.gradle +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/build.gradle @@ -113,7 +113,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 a90f98e2152b..f825b7dffe10 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.2", - "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 08ffdd44ecbf..b52cfb0a8c26 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/pom.xml +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/pom.xml @@ -281,9 +281,14 @@ ${gson-fire-version}
- 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.apache.commons 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 93328801c2e1..b0c96079b76e 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 @@ -24,8 +24,6 @@ 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; @@ -52,13 +50,7 @@ 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.*; /** *

ApiClient class.

@@ -153,35 +145,36 @@ public ApiClient(String clientId, String clientSecret, Map param } /** - * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters - * - * @param basePath base path - * @param clientId client ID - * @param clientSecret client secret - * @param parameters a {@link java.util.Map} of parameters + * * Constructor for ApiClient configured with base path, client ID, secret, and additional parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map 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 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.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")); @@ -191,6 +184,45 @@ public ApiClient(String basePath, String clientId, String clientSecret, MapemptyList()); } @@ -659,21 +691,6 @@ public ApiClient setWriteTimeout(int writeTimeout) { 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 000000000000..5de9aa949ff0 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java @@ -0,0 +1,63 @@ +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 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 000000000000..eec4d8350f0b --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java @@ -0,0 +1,103 @@ +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 params; + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map 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 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 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 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 000000000000..5c319ef0a5f6 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java @@ -0,0 +1,62 @@ +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 000000000000..f4f8b398f86d --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java @@ -0,0 +1,78 @@ +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 3cd173237152..e0fffde470ac 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 c88a30679cf9..106bd8b0237a 100644 --- a/samples/client/petstore/java/okhttp-gson/build.gradle +++ b/samples/client/petstore/java/okhttp-gson/build.gradle @@ -113,7 +113,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 95fad49a3303..101daf95479f 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.2", - "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 43e3d9f548f1..abbd8a20dda9 100644 --- a/samples/client/petstore/java/okhttp-gson/pom.xml +++ b/samples/client/petstore/java/okhttp-gson/pom.xml @@ -281,9 +281,14 @@ ${gson-fire-version}
- 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.apache.commons 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 93328801c2e1..b0c96079b76e 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 @@ -24,8 +24,6 @@ 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; @@ -52,13 +50,7 @@ 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.*; /** *

ApiClient class.

@@ -153,35 +145,36 @@ public ApiClient(String clientId, String clientSecret, Map param } /** - * Constructor for ApiClient to support access token retry on 401/403 configured with base path, client ID, secret, and additional parameters - * - * @param basePath base path - * @param clientId client ID - * @param clientSecret client secret - * @param parameters a {@link java.util.Map} of parameters + * * Constructor for ApiClient configured with base path, client ID, secret, and additional parameters */ public ApiClient(String basePath, String clientId, String clientSecret, Map 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 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.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")); @@ -191,6 +184,45 @@ public ApiClient(String basePath, String clientId, String clientSecret, MapemptyList()); } @@ -659,21 +691,6 @@ public ApiClient setWriteTimeout(int writeTimeout) { 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 000000000000..5de9aa949ff0 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java @@ -0,0 +1,63 @@ +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 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 000000000000..eec4d8350f0b --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrant.java @@ -0,0 +1,103 @@ +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 params; + public OAuthAuthorizationCodeGrant(String clientId, String clientSecret, String authorizationBaseUrl, String accessTokenEndpoint, String callbackUrl, Map 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 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 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 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 000000000000..5c319ef0a5f6 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthClientCredentialsGrant.java @@ -0,0 +1,62 @@ +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/OAuthOkHttpClient.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthOkHttpClient.java deleted file mode 100644 index 1c8ac2dc0cce..000000000000 --- 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 execute(OAuthClientRequest request, Map headers, - String requestMethod, Class responseClass) - throws OAuthSystemException, OAuthProblemException { - - MediaType mediaType = MediaType.parse("application/json"); - Request.Builder requestBuilder = new Request.Builder().url(request.getLocationUri()); - - if(headers != null) { - for (Entry 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/OAuthPasswordGrant.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java new file mode 100644 index 000000000000..f4f8b398f86d --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthPasswordGrant.java @@ -0,0 +1,78 @@ +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/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 911df8d3a37d..000000000000 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/RetryingOAuth.java +++ /dev/null @@ -1,182 +0,0 @@ -package org.openapitools.client.auth; - -import org.openapitools.client.ApiException; -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.net.URI; -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 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 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 queryParams, Map headerParams, Map cookieParams, - String payload, String method, URI uri) throws ApiException { - // 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 47f8fed5c86c..ad0353d6395d 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 @@ -35,14 +35,11 @@ import org.openapitools.client.auth.*; import org.openapitools.client.model.*; import org.openapitools.client.model.Pet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** API tests for PetApi */ 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"; @@ -379,7 +376,6 @@ public void testDeletePet() throws Exception { 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/OAuthAuthorizationCodeGrantTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrantTest.java new file mode 100644 index 000000000000..c7459003f072 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthAuthorizationCodeGrantTest.java @@ -0,0 +1,96 @@ +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 org.openapitools.client.ApiException; + +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.emptyMap()); + oauth.setAccessToken("expired-access-token"); + FieldUtils.writeField(oauth, "service", mockOAuthService(), true); + } + + @Test + public void testApplyToParams() throws IOException, ExecutionException, InterruptedException, ApiException { + List queryParams = new ArrayList(); + Map headerParams = new HashMap(); + Map cookieParams = new HashMap(); + + oauth.applyToParams(queryParams, headerParams, cookieParams, null, null, null); + + // 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, null, null, null); + 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() { + @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; + } +} \ No newline at end of file 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 000000000000..53ed1a95feef --- /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.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 org.openapitools.client.ApiException; + +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, ApiException { + List queryParams = new ArrayList(); + Map headerParams = new HashMap(); + Map cookieParams = new HashMap(); + + oauth.applyToParams(queryParams, headerParams, cookieParams, null, null, null); + + // 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, null, null, null); + 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() { + @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 000000000000..9809df0f4e46 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/OAuthPasswordGrantTest.java @@ -0,0 +1,76 @@ +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 org.openapitools.client.ApiException; + +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, ApiException { + List queryParams = new ArrayList(); + Map headerParams = new HashMap(); + Map cookieParams = new HashMap(); + + oauth.applyToParams(queryParams, headerParams, cookieParams, null, null, null); + + // 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, null, null, null); + 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() { + @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; + } +} 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 7e0b2bec4b58..000000000000 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/auth/RetryingOAuthTest.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.openapitools.client.auth; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -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 okhttp3.*; -import okhttp3.Interceptor.Chain; -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; - -public class RetryingOAuthTest { - - private RetryingOAuth oauth; - - @Before - public void setUp() throws Exception { - oauth = - new RetryingOAuth( - "_clientId", - "_clientSecret", - OAuthFlow.accessCode, - "https://token.example.com", - Collections.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 callable = - new Callable() { - @Override - public Response call() throws Exception { - return oauth.intercept(mockChain()); - } - }; - ExecutorService executor = Executors.newFixedThreadPool(2); - try { - Future response1 = executor.submit(callable); - Future 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() { - @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() { - @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; - } -}