diff --git a/modules/openapi-generator-gradle-plugin/gradlew.bat b/modules/openapi-generator-gradle-plugin/gradlew.bat index 24467a141f7..9618d8d9607 100644 --- a/modules/openapi-generator-gradle-plugin/gradlew.bat +++ b/modules/openapi-generator-gradle-plugin/gradlew.bat @@ -1,100 +1,100 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega 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 a0ce92fac1c..f7053bd900c 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 @@ -392,6 +392,10 @@ public class JavaClientCodegen extends AbstractJavaCodegen forceSerializationLibrary(SERIALIZATION_LIBRARY_JACKSON); supportingFiles.add(new SupportingFile("ParamExpander.mustache", invokerFolder, "ParamExpander.java")); supportingFiles.add(new SupportingFile("EncodingUtils.mustache", invokerFolder, "EncodingUtils.java")); + supportingFiles.add(new SupportingFile("auth/DefaultApi20Impl.mustache", authFolder, "DefaultApi20Impl.java")); + supportingFiles.add(new SupportingFile("auth/OauthPasswordGrant.mustache", authFolder, "OauthPasswordGrant.java")); + supportingFiles.add(new SupportingFile("auth/OauthClientCredentialsGrant.mustache", authFolder, "OauthClientCredentialsGrant.java")); + } else if (OKHTTP_GSON.equals(getLibrary()) || StringUtils.isEmpty(getLibrary())) { // the "okhttp-gson" library template requires "ApiCallback.mustache" for async call supportingFiles.add(new SupportingFile("ApiCallback.mustache", invokerFolder, "ApiCallback.java")); diff --git a/modules/openapi-generator/src/main/resources/Java/auth/OAuthFlow.mustache b/modules/openapi-generator/src/main/resources/Java/auth/OAuthFlow.mustache index 002e9572f33..07b7f3aa673 100644 --- a/modules/openapi-generator/src/main/resources/Java/auth/OAuthFlow.mustache +++ b/modules/openapi-generator/src/main/resources/Java/auth/OAuthFlow.mustache @@ -2,6 +2,10 @@ package {{invokerPackage}}.auth; +{{>generatedAnnotation}} public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiClient.mustache index 691f337c7c5..54201a1c615 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/ApiClient.mustache @@ -2,11 +2,8 @@ package {{invokerPackage}}; import java.util.LinkedHashMap; import java.util.Map; - -{{#hasOAuthMethods}} -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -{{/hasOAuthMethods}} +import java.util.logging.Level; +import java.util.logging.Logger; {{#threetenbp}} import org.threeten.bp.*; @@ -41,6 +38,8 @@ import {{invokerPackage}}.auth.OAuth.AccessTokenListener; {{>generatedAnnotation}} public class ApiClient { + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + public interface Api {} protected ObjectMapper objectMapper; @@ -60,6 +59,7 @@ public class ApiClient { public ApiClient(String[] authNames) { this(); for(String authName : authNames) { + log.log(Level.FINE, "Creating authentication {0}", authName); {{#hasAuthMethods}} RequestInterceptor auth; {{#authMethods}}if ("{{name}}".equals(authName)) { @@ -75,7 +75,7 @@ public class ApiClient { auth = new ApiKeyAuth({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{#isKeyInQuery}}"query"{{/isKeyInQuery}}{{#isKeyInCookie}}"cookie"{{/isKeyInCookie}}, "{{keyParamName}}"); {{/isApiKey}} {{#isOAuth}} - auth = new OAuth(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); + auth = buildOauthRequestInterceptor(OAuthFlow.{{flow}}, "{{authorizationUrl}}", "{{tokenUrl}}", "{{#scopes}}{{scope}}{{^-last}}, {{/-last}}{{/scopes}}"); {{/isOAuth}} } else {{/authMethods}}{ throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); @@ -106,36 +106,6 @@ public class ApiClient { this.setApiKey(apiKey); } - /** - * Helper constructor for single basic auth or password oauth2 - * @param authName - * @param username - * @param password - */ - public ApiClient(String authName, String username, String password) { - this(authName); - this.setCredentials(username, password); - } - - {{#hasOAuthMethods}} - /** - * Helper constructor for single password oauth2 - * @param authName - * @param clientId - * @param secret - * @param username - * @param password - */ - public ApiClient(String authName, String clientId, String secret, String username, String password) { - this(authName); - this.getTokenEndPoint() - .setClientId(clientId) - .setClientSecret(secret) - .setUsername(username) - .setPassword(password); - } - - {{/hasOAuthMethods}} public String getBasePath() { return basePath; } @@ -190,10 +160,25 @@ public class ApiClient { return objectMapper; } + private RequestInterceptor buildOauthRequestInterceptor(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + switch (flow) { + case password: + return new OauthPasswordGrant(tokenUrl, scopes); + case application: + return new OauthClientCredentialsGrant(authorizationUrl, tokenUrl, scopes); + default: + throw new RuntimeException("Oauth flow \"" + flow + "\" is not implemented"); + } + } + public ObjectMapper getObjectMapper(){ return objectMapper; } + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + /** * Creates a feign client for given API interface. * @@ -240,19 +225,13 @@ public class ApiClient { return contentTypes[0]; } - /** * Helper method to configure the bearer token. * @param bearerToken the bearer token. */ public void setBearerToken(String bearerToken) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBearerAuth) { - ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); - return; - } - } - throw new RuntimeException("No Bearer authentication configured!"); + HttpBearerAuth apiAuthorization = getAuthorization(HttpBearerAuth.class); + apiAuthorization.setBearerToken(bearerToken); } /** @@ -260,66 +239,39 @@ public class ApiClient { * @param apiKey API key */ public void setApiKey(String apiKey) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof ApiKeyAuth) { - ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; - keyAuth.setApiKey(apiKey); - return ; - } - } - throw new RuntimeException("No API key authentication configured!"); + ApiKeyAuth apiAuthorization = getAuthorization(ApiKeyAuth.class); + apiAuthorization.setApiKey(apiKey); } /** - * Helper method to configure the username/password for basic auth or password OAuth + * Helper method to configure the username/password for basic auth * @param username Username * @param password Password */ public void setCredentials(String username, String password) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBasicAuth) { - HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; - basicAuth.setCredentials(username, password); - return; - } - {{#hasOAuthMethods}} - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); - return; - } - {{/hasOAuthMethods}} - } - throw new RuntimeException("No Basic authentication or OAuth configured!"); + HttpBasicAuth apiAuthorization = getAuthorization(HttpBasicAuth.class); + apiAuthorization.setCredentials(username, password); } {{#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 + * Helper method to configure the client credentials for Oauth + * @param username Username + * @param password Password */ - public TokenRequestBuilder getTokenEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getTokenRequestBuilder(); - } - } - return null; + public void setClientCredentials(String clientId, String clientSecret) { + OauthClientCredentialsGrant authorization = getAuthorization(OauthClientCredentialsGrant.class); + authorization.configure(clientId, clientSecret); } /** - * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Authentication request builder + * Helper method to configure the username/password for Oauth password grant + * @param username Username + * @param password Password */ - public AuthenticationRequestBuilder getAuthorizationEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getAuthenticationRequestBuilder(); - } - } - return null; + public void setOauthPassword(String username, String password, String clientId, String clientSecret) { + OauthPasswordGrant apiAuthorization = getAuthorization(OauthPasswordGrant.class); + apiAuthorization.configure(username, password, clientId, clientSecret); } /** @@ -327,14 +279,9 @@ public class ApiClient { * @param accessToken Access Token * @param expiresIn Validity period in seconds */ - public void setAccessToken(String accessToken, Long expiresIn) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.setAccessToken(accessToken, expiresIn); - return; - } - } + public void setAccessToken(String accessToken, Integer expiresIn) { + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.setAccessToken(accessToken, expiresIn); } /** @@ -344,19 +291,7 @@ public class ApiClient { * @param redirectURI Redirect URI */ public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder() - .setClientId(clientId) - .setClientSecret(clientSecret) - .setRedirectURI(redirectURI); - oauth.getAuthenticationRequestBuilder() - .setClientId(clientId) - .setRedirectURI(redirectURI); - return; - } - } + throw new RuntimeException("Not implemented"); } /** @@ -364,13 +299,8 @@ public class ApiClient { * @param accessTokenListener Acesss token listener */ public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.registerAccessTokenListener(accessTokenListener); - return; - } - } + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.registerAccessTokenListener(accessTokenListener); } {{/hasOAuthMethods}} @@ -396,4 +326,11 @@ public class ApiClient { feignBuilder.requestInterceptor(authorization); } + private T getAuthorization(Class type) { + return (T) apiAuthorizations.values() + .stream() + .filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass())) + .findFirst() + .orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!")); + } } diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/README.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/README.mustache index a0fac9d41df..acab659406d 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/feign/README.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/README.mustache @@ -32,6 +32,41 @@ After the client library is installed/deployed, you can use it in your Maven pro ``` +And to use the api you can follow the examples bellow: + +```java + + //Set bearer token manually + ApiClient apiClient = new ApiClient("petstore_auth_client"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setAccessToken("TOKEN", 10000); + + //Use api key + ApiClient apiClient = new ApiClient("api_key", "API KEY"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + + //Use http basic authentication + ApiClient apiClient = new ApiClient("basicAuth"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setCredentials("username", "password"); + + //Oauth password + ApiClient apiClient = new ApiClient("oauth_password"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setOauthPassword("username", "password", "client_id", "client_secret"); + + //Oauth client credentials flow + ApiClient apiClient = new ApiClient("oauth_client_credentials"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setClientCredentials("client_id", "client_secret"); + + PetApi petApi = apiClient.buildClient(PetApi.class); + Pet petById = petApi.getPetById(12345L); + + System.out.println(petById); + } +``` + ## Recommendation It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. @@ -40,4 +75,3 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea {{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} {{/-last}}{{/apis}}{{/apiInfo}} - diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/DefaultApi20Impl.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/DefaultApi20Impl.mustache new file mode 100644 index 00000000000..72b0a00495e --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/DefaultApi20Impl.mustache @@ -0,0 +1,47 @@ +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; + + protected DefaultApi20Impl(String authorizationBaseUrl, String accessTokenEndpoint) { + this.authorizationBaseUrl = authorizationBaseUrl; + this.accessTokenEndpoint = accessTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OAuth.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OAuth.mustache index b451e97ae6e..864ee3fe3a5 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OAuth.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OAuth.mustache @@ -1,198 +1,81 @@ package {{invokerPackage}}.auth; -import java.io.IOException; -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.oltu.oauth2.client.HttpClient; -import org.apache.oltu.oauth2.client.OAuthClient; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -import org.apache.oltu.oauth2.client.response.OAuthClientResponse; -import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; -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 org.apache.oltu.oauth2.common.token.BasicOAuthToken; - -import feign.Client; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; import feign.Request.HttpMethod; -import feign.Request.Options; import feign.RequestInterceptor; import feign.RequestTemplate; -import feign.Response; import feign.RetryableException; -import feign.Util; -import {{invokerPackage}}.StringUtil; +{{>generatedAnnotation}} +public abstract class OAuth implements RequestInterceptor { -public class OAuth implements RequestInterceptor { + static final int MILLIS_PER_SECOND = 1000; - static final int MILLIS_PER_SECOND = 1000; + public interface AccessTokenListener { + void notify(OAuth2AccessToken token); + } - public interface AccessTokenListener { - void notify(BasicOAuthToken token); + private volatile String accessToken; + private Long expirationTimeMillis; + private AccessTokenListener accessTokenListener; + + protected OAuth20Service service; + protected String scopes; + protected String authorizationUrl; + protected String tokenUrl; + + public OAuth(String authorizationUrl, String tokenUrl, String scopes) { + this.scopes = scopes; + this.authorizationUrl = authorizationUrl; + this.tokenUrl = tokenUrl; + } + + @Override + public void apply(RequestTemplate template) { + // If the request already have an authorization (eg. Basic auth), do nothing + if (template.headers().containsKey("Authorization")) { + return; } - - private volatile String accessToken; - private Long expirationTimeMillis; - private OAuthClient oauthClient; - private TokenRequestBuilder tokenRequestBuilder; - private AuthenticationRequestBuilder authenticationRequestBuilder; - private AccessTokenListener accessTokenListener; - - public OAuth(Client client, TokenRequestBuilder requestBuilder) { - this.oauthClient = new OAuthClient(new OAuthFeignClient(client)); - this.tokenRequestBuilder = requestBuilder; + // If first time, get the token + if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { + updateAccessToken(template); } - - public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); - - switch(flow) { - case accessCode: - case implicit: - tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); - break; - case password: - tokenRequestBuilder.setGrantType(GrantType.PASSWORD); - break; - case application: - tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); - break; - default: - break; - } - authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + if (getAccessToken() != null) { + template.header("Authorization", "Bearer " + getAccessToken()); } + } - public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes); + private synchronized void updateAccessToken(RequestTemplate template) { + OAuth2AccessToken accessTokenResponse; + try { + accessTokenResponse = getOAuth2AccessToken(); + } catch (Exception e) { + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); } - - @Override - public void apply(RequestTemplate template) { - // If the request already have an authorization (eg. Basic auth), do nothing - if (template.headers().containsKey("Authorization")) { - return; - } - // If first time, get the token - if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { - updateAccessToken(template); - } - if (getAccessToken() != null) { - template.header("Authorization", "Bearer " + getAccessToken()); - } + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); + if (accessTokenListener != null) { + accessTokenListener.notify(accessTokenResponse); + } } + } - public synchronized void updateAccessToken(RequestTemplate template) { - OAuthJSONAccessTokenResponse accessTokenResponse; - try { - accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); - } catch (Exception e) { - throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); - } - if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { - setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); - if (accessTokenListener != null) { - accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); - } - } - } + abstract OAuth2AccessToken getOAuth2AccessToken(); - public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - this.accessTokenListener = accessTokenListener; - } + abstract OAuthFlow getFlow(); - public synchronized String getAccessToken() { - return accessToken; - } + public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } - public synchronized void setAccessToken(String accessToken, Long expiresIn) { - this.accessToken = accessToken; - this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; - } + public synchronized String getAccessToken() { + return accessToken; + } - public TokenRequestBuilder getTokenRequestBuilder() { - return tokenRequestBuilder; - } + public synchronized void setAccessToken(String accessToken, Integer expiresIn) { + this.accessToken = accessToken; + this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + } - public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { - this.tokenRequestBuilder = tokenRequestBuilder; - } - - public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { - return authenticationRequestBuilder; - } - - public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { - this.authenticationRequestBuilder = authenticationRequestBuilder; - } - - public OAuthClient getOauthClient() { - return oauthClient; - } - - public void setOauthClient(OAuthClient oauthClient) { - this.oauthClient = oauthClient; - } - - public void setOauthClient(Client client) { - this.oauthClient = new OAuthClient( new OAuthFeignClient(client)); - } - - public static class OAuthFeignClient implements HttpClient { - - private Client client; - - public OAuthFeignClient() { - this.client = new Client.Default(null, null); - } - - public OAuthFeignClient(Client client) { - this.client = client; - } - - public T execute(OAuthClientRequest request, Map headers, - String requestMethod, Class responseClass) - throws OAuthSystemException, OAuthProblemException { - - RequestTemplate req = new RequestTemplate() - .append(request.getLocationUri()) - .method(requestMethod) - .body(request.getBody()); - - for (Entry entry : headers.entrySet()) { - req.header(entry.getKey(), entry.getValue()); - } - Response feignResponse; - String body = ""; - try { - feignResponse = client.execute(req.request(), new Options()); - body = Util.toString(feignResponse.body().asReader()); - } catch (IOException e) { - throw new OAuthSystemException(e); - } - - String contentType = null; - Collection contentTypeHeader = feignResponse.headers().get("Content-Type"); - if(contentTypeHeader != null) { - contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";"); - } - - return OAuthClientResponseFactory.createCustomResponse( - body, - contentType, - feignResponse.status(), - responseClass - ); - } - - public void shutdown() { - // Nothing to do here - } - } -} +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OauthClientCredentialsGrant.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OauthClientCredentialsGrant.mustache new file mode 100644 index 00000000000..ef22c211637 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OauthClientCredentialsGrant.mustache @@ -0,0 +1,39 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +{{>generatedAnnotation}} +public class OauthClientCredentialsGrant extends OAuth { + + public OauthClientCredentialsGrant(String authorizationUrl, String tokenUrl, String scopes) { + super(authorizationUrl, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenClientCredentialsGrant(scopes); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.application; + } + + /** + * Configures the client credentials flow + * + * @param clientId + * @param clientSecret + */ + public void configure(String clientId, String clientSecret) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OauthPasswordGrant.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OauthPasswordGrant.mustache new file mode 100644 index 00000000000..870c3755a8b --- /dev/null +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/auth/OauthPasswordGrant.mustache @@ -0,0 +1,48 @@ +package {{invokerPackage}}.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +{{>generatedAnnotation}} +public class OauthPasswordGrant extends OAuth { + + private String username; + private String password; + + public OauthPasswordGrant(String tokenUrl, String scopes) { + super(null, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenPasswordGrant(username, password); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.password; + } + + /** + * Configures Oauth password grant flow + * Note: this flow is deprecated. + * + * @param username + * @param password + * @param clientId + * @param clientSecret + */ + public void configure(String username, String password, String clientId, String clientSecret) { + this.username = username; + this.password = password; + //TODO the clientId and secret are optional according with the RFC + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/build.gradle.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/build.gradle.mustache index 3e00fb91797..ae4a04c11b3 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/feign/build.gradle.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/build.gradle.mustache @@ -33,20 +33,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - {{#supportJava6}} - sourceCompatibility JavaVersion.VERSION_1_6 - targetCompatibility JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} } // Rename the aar correctly @@ -91,20 +79,8 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - {{#supportJava6}} - sourceCompatibility = JavaVersion.VERSION_1_6 - targetCompatibility = JavaVersion.VERSION_1_6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 - {{/java8}} - {{^java8}} - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 - {{/java8}} - {{/supportJava6}} install { repositories.mavenInstaller { @@ -131,7 +107,7 @@ ext { feign_version = "10.11" feign_form_version = "3.8.0" junit_version = "4.13.1" - oltu_version = "1.0.1" + scribejava_version = "8.0.0" } dependencies { @@ -156,7 +132,8 @@ dependencies { {{#threetenbp}} implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" {{/threetenbp}} - implementation "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + implementation "com.brsanthu:migbase64:2.2" + implementation "com.github.scribejava:scribejava-core:$scribejava_version" implementation "com.brsanthu:migbase64:2.2" implementation 'javax.annotation:javax.annotation-api:1.3.2' testImplementation "junit:junit:$junit_version" diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/build.sbt.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/build.sbt.mustache index 322abb2a5cb..218469b0d57 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/feign/build.sbt.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/build.sbt.mustache @@ -19,7 +19,7 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-{{^java8}}joda{{/java8}}{{#java8}}jsr310{{/java8}}" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "com.github.scribejava" % "scribejava-core" % "8.0.0" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13.1" % "test", diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/feign/pom.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/feign/pom.mustache index e9abe7dbaad..ce830af9e11 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/feign/pom.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/feign/pom.mustache @@ -161,17 +161,7 @@ 3.1.1 none - {{#supportJava6}} - 1.6 - {{/supportJava6}} - {{^supportJava6}} - {{#java8}} - 1.8 - {{/java8}} - {{^java8}} - 1.7 - {{/java8}} - {{/supportJava6}} + 1.8 @@ -282,40 +272,38 @@ {{/openApiNullable}} {{#withXml}} - - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${jackson-version} - - + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson-version} + {{/withXml}} {{#joda}} - - com.fasterxml.jackson.datatype - jackson-datatype-joda - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-version} + {{/joda}} {{#java8}} - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${jackson-version} - + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-version} + {{/java8}} {{#threetenbp}} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - + + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + {{/threetenbp}} - org.apache.oltu.oauth2 - org.apache.oltu.oauth2.client - ${oltu-version} + com.github.scribejava + scribejava-core + ${scribejava-version} javax.annotation @@ -346,7 +334,7 @@ UTF-8 - {{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}} + 1.8 ${java.version} ${java.version} 1.5.24 @@ -363,6 +351,6 @@ 1.3.2 4.13.1 1.0.0 - 1.0.1 + 8.0.0 diff --git a/samples/client/petstore/java/feign-no-nullable/.openapi-generator/FILES b/samples/client/petstore/java/feign-no-nullable/.openapi-generator/FILES index 1e341310444..cd394fffa07 100644 --- a/samples/client/petstore/java/feign-no-nullable/.openapi-generator/FILES +++ b/samples/client/petstore/java/feign-no-nullable/.openapi-generator/FILES @@ -28,10 +28,13 @@ src/main/java/org/openapitools/client/api/PetApi.java 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/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/OAuthFlow.java +src/main/java/org/openapitools/client/auth/OauthClientCredentialsGrant.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/feign-no-nullable/README.md b/samples/client/petstore/java/feign-no-nullable/README.md index 86ec963c508..8a2d579d815 100644 --- a/samples/client/petstore/java/feign-no-nullable/README.md +++ b/samples/client/petstore/java/feign-no-nullable/README.md @@ -32,6 +32,41 @@ After the client library is installed/deployed, you can use it in your Maven pro ``` +And to use the api you can follow the examples bellow: + +```java + + //Set bearer token manually + ApiClient apiClient = new ApiClient("petstore_auth_client"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setAccessToken("TOKEN", 10000); + + //Use api key + ApiClient apiClient = new ApiClient("api_key", "API KEY"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + + //Use http basic authentication + ApiClient apiClient = new ApiClient("basicAuth"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setCredentials("username", "password"); + + //Oauth password + ApiClient apiClient = new ApiClient("oauth_password"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setOauthPassword("username", "password", "client_id", "client_secret"); + + //Oauth client credentials flow + ApiClient apiClient = new ApiClient("oauth_client_credentials"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setClientCredentials("client_id", "client_secret"); + + PetApi petApi = apiClient.buildClient(PetApi.class); + Pet petById = petApi.getPetById(12345L); + + System.out.println(petById); + } +``` + ## Recommendation It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. @@ -40,4 +75,3 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea - diff --git a/samples/client/petstore/java/feign-no-nullable/build.gradle b/samples/client/petstore/java/feign-no-nullable/build.gradle index 714dcc365b1..69082b38baf 100644 --- a/samples/client/petstore/java/feign-no-nullable/build.gradle +++ b/samples/client/petstore/java/feign-no-nullable/build.gradle @@ -33,8 +33,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } // Rename the aar correctly @@ -79,8 +79,8 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 install { repositories.mavenInstaller { @@ -102,7 +102,7 @@ ext { feign_version = "10.11" feign_form_version = "3.8.0" junit_version = "4.13.1" - oltu_version = "1.0.1" + scribejava_version = "8.0.0" } dependencies { @@ -116,7 +116,8 @@ dependencies { implementation "com.fasterxml.jackson.core:jackson-annotations:$jackson_version" implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" - implementation "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + implementation "com.brsanthu:migbase64:2.2" + implementation "com.github.scribejava:scribejava-core:$scribejava_version" implementation "com.brsanthu:migbase64:2.2" implementation 'javax.annotation:javax.annotation-api:1.3.2' testImplementation "junit:junit:$junit_version" diff --git a/samples/client/petstore/java/feign-no-nullable/build.sbt b/samples/client/petstore/java/feign-no-nullable/build.sbt index e2f16203405..89fe08d2939 100644 --- a/samples/client/petstore/java/feign-no-nullable/build.sbt +++ b/samples/client/petstore/java/feign-no-nullable/build.sbt @@ -19,7 +19,7 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "com.github.scribejava" % "scribejava-core" % "8.0.0" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13.1" % "test", diff --git a/samples/client/petstore/java/feign-no-nullable/pom.xml b/samples/client/petstore/java/feign-no-nullable/pom.xml index 21d57629126..a0d99f21447 100644 --- a/samples/client/petstore/java/feign-no-nullable/pom.xml +++ b/samples/client/petstore/java/feign-no-nullable/pom.xml @@ -154,7 +154,7 @@ 3.1.1 none - 1.7 + 1.8 @@ -257,15 +257,15 @@ jackson-databind ${jackson-databind-version} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - - org.apache.oltu.oauth2 - org.apache.oltu.oauth2.client - ${oltu-version} + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + + com.github.scribejava + scribejava-core + ${scribejava-version} javax.annotation @@ -296,7 +296,7 @@ UTF-8 - 1.7 + 1.8 ${java.version} ${java.version} 1.5.24 @@ -308,6 +308,6 @@ 1.3.2 4.13.1 1.0.0 - 1.0.1 + 8.0.0 diff --git a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/ApiClient.java index 69315cfc70c..87b9f7bbe27 100644 --- a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/ApiClient.java @@ -2,9 +2,8 @@ package org.openapitools.client; import java.util.LinkedHashMap; import java.util.Map; - -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import java.util.logging.Level; +import java.util.logging.Logger; import org.threeten.bp.*; @@ -24,6 +23,8 @@ import org.openapitools.client.auth.OAuth.AccessTokenListener; @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public class ApiClient { + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + public interface Api {} protected ObjectMapper objectMapper; @@ -43,6 +44,7 @@ public class ApiClient { public ApiClient(String[] authNames) { this(); for(String authName : authNames) { + log.log(Level.FINE, "Creating authentication {0}", authName); RequestInterceptor auth; if ("api_key".equals(authName)) { auth = new ApiKeyAuth("header", "api_key"); @@ -51,7 +53,7 @@ public class ApiClient { } else if ("http_basic_test".equals(authName)) { auth = new HttpBasicAuth(); } else if ("petstore_auth".equals(authName)) { - auth = new OAuth(OAuthFlow.implicit, "http://petstore.swagger.io/api/oauth/dialog", "", "write:pets, read:pets"); + auth = buildOauthRequestInterceptor(OAuthFlow.implicit, "http://petstore.swagger.io/api/oauth/dialog", "", "write:pets, read:pets"); } else { throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); } @@ -77,34 +79,6 @@ public class ApiClient { this.setApiKey(apiKey); } - /** - * Helper constructor for single basic auth or password oauth2 - * @param authName - * @param username - * @param password - */ - public ApiClient(String authName, String username, String password) { - this(authName); - this.setCredentials(username, password); - } - - /** - * Helper constructor for single password oauth2 - * @param authName - * @param clientId - * @param secret - * @param username - * @param password - */ - public ApiClient(String authName, String clientId, String secret, String username, String password) { - this(authName); - this.getTokenEndPoint() - .setClientId(clientId) - .setClientSecret(secret) - .setUsername(username) - .setPassword(password); - } - public String getBasePath() { return basePath; } @@ -147,10 +121,25 @@ public class ApiClient { return objectMapper; } + private RequestInterceptor buildOauthRequestInterceptor(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + switch (flow) { + case password: + return new OauthPasswordGrant(tokenUrl, scopes); + case application: + return new OauthClientCredentialsGrant(authorizationUrl, tokenUrl, scopes); + default: + throw new RuntimeException("Oauth flow \"" + flow + "\" is not implemented"); + } + } + public ObjectMapper getObjectMapper(){ return objectMapper; } + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + /** * Creates a feign client for given API interface. * @@ -197,19 +186,13 @@ public class ApiClient { return contentTypes[0]; } - /** * Helper method to configure the bearer token. * @param bearerToken the bearer token. */ public void setBearerToken(String bearerToken) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBearerAuth) { - ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); - return; - } - } - throw new RuntimeException("No Bearer authentication configured!"); + HttpBearerAuth apiAuthorization = getAuthorization(HttpBearerAuth.class); + apiAuthorization.setBearerToken(bearerToken); } /** @@ -217,63 +200,38 @@ public class ApiClient { * @param apiKey API key */ public void setApiKey(String apiKey) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof ApiKeyAuth) { - ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; - keyAuth.setApiKey(apiKey); - return ; - } - } - throw new RuntimeException("No API key authentication configured!"); + ApiKeyAuth apiAuthorization = getAuthorization(ApiKeyAuth.class); + apiAuthorization.setApiKey(apiKey); } /** - * Helper method to configure the username/password for basic auth or password OAuth + * Helper method to configure the username/password for basic auth * @param username Username * @param password Password */ public void setCredentials(String username, String password) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBasicAuth) { - HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; - basicAuth.setCredentials(username, password); - return; - } - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); - return; - } - } - throw new RuntimeException("No Basic authentication or OAuth configured!"); + HttpBasicAuth apiAuthorization = getAuthorization(HttpBasicAuth.class); + apiAuthorization.setCredentials(username, password); } /** - * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Token request builder + * Helper method to configure the client credentials for Oauth + * @param username Username + * @param password Password */ - public TokenRequestBuilder getTokenEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getTokenRequestBuilder(); - } - } - return null; + public void setClientCredentials(String clientId, String clientSecret) { + OauthClientCredentialsGrant authorization = getAuthorization(OauthClientCredentialsGrant.class); + authorization.configure(clientId, clientSecret); } /** - * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Authentication request builder + * Helper method to configure the username/password for Oauth password grant + * @param username Username + * @param password Password */ - public AuthenticationRequestBuilder getAuthorizationEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getAuthenticationRequestBuilder(); - } - } - return null; + public void setOauthPassword(String username, String password, String clientId, String clientSecret) { + OauthPasswordGrant apiAuthorization = getAuthorization(OauthPasswordGrant.class); + apiAuthorization.configure(username, password, clientId, clientSecret); } /** @@ -281,14 +239,9 @@ public class ApiClient { * @param accessToken Access Token * @param expiresIn Validity period in seconds */ - public void setAccessToken(String accessToken, Long expiresIn) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.setAccessToken(accessToken, expiresIn); - return; - } - } + public void setAccessToken(String accessToken, Integer expiresIn) { + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.setAccessToken(accessToken, expiresIn); } /** @@ -298,19 +251,7 @@ public class ApiClient { * @param redirectURI Redirect URI */ public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder() - .setClientId(clientId) - .setClientSecret(clientSecret) - .setRedirectURI(redirectURI); - oauth.getAuthenticationRequestBuilder() - .setClientId(clientId) - .setRedirectURI(redirectURI); - return; - } - } + throw new RuntimeException("Not implemented"); } /** @@ -318,13 +259,8 @@ public class ApiClient { * @param accessTokenListener Acesss token listener */ public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.registerAccessTokenListener(accessTokenListener); - return; - } - } + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.registerAccessTokenListener(accessTokenListener); } /** @@ -349,4 +285,11 @@ public class ApiClient { feignBuilder.requestInterceptor(authorization); } + private T getAuthorization(Class type) { + return (T) apiAuthorizations.values() + .stream() + .filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass())) + .findFirst() + .orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!")); + } } diff --git a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java new file mode 100644 index 00000000000..80db21111f9 --- /dev/null +++ b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java @@ -0,0 +1,47 @@ +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; + + protected DefaultApi20Impl(String authorizationBaseUrl, String accessTokenEndpoint) { + this.authorizationBaseUrl = authorizationBaseUrl; + this.accessTokenEndpoint = accessTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OAuth.java b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OAuth.java index f59ad4a94ba..d41eca7a0a5 100644 --- a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OAuth.java +++ b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OAuth.java @@ -1,198 +1,81 @@ package org.openapitools.client.auth; -import java.io.IOException; -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.oltu.oauth2.client.HttpClient; -import org.apache.oltu.oauth2.client.OAuthClient; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -import org.apache.oltu.oauth2.client.response.OAuthClientResponse; -import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; -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 org.apache.oltu.oauth2.common.token.BasicOAuthToken; - -import feign.Client; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; import feign.Request.HttpMethod; -import feign.Request.Options; import feign.RequestInterceptor; import feign.RequestTemplate; -import feign.Response; import feign.RetryableException; -import feign.Util; -import org.openapitools.client.StringUtil; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public abstract class OAuth implements RequestInterceptor { -public class OAuth implements RequestInterceptor { + static final int MILLIS_PER_SECOND = 1000; - static final int MILLIS_PER_SECOND = 1000; + public interface AccessTokenListener { + void notify(OAuth2AccessToken token); + } - public interface AccessTokenListener { - void notify(BasicOAuthToken token); + private volatile String accessToken; + private Long expirationTimeMillis; + private AccessTokenListener accessTokenListener; + + protected OAuth20Service service; + protected String scopes; + protected String authorizationUrl; + protected String tokenUrl; + + public OAuth(String authorizationUrl, String tokenUrl, String scopes) { + this.scopes = scopes; + this.authorizationUrl = authorizationUrl; + this.tokenUrl = tokenUrl; + } + + @Override + public void apply(RequestTemplate template) { + // If the request already have an authorization (eg. Basic auth), do nothing + if (template.headers().containsKey("Authorization")) { + return; } - - private volatile String accessToken; - private Long expirationTimeMillis; - private OAuthClient oauthClient; - private TokenRequestBuilder tokenRequestBuilder; - private AuthenticationRequestBuilder authenticationRequestBuilder; - private AccessTokenListener accessTokenListener; - - public OAuth(Client client, TokenRequestBuilder requestBuilder) { - this.oauthClient = new OAuthClient(new OAuthFeignClient(client)); - this.tokenRequestBuilder = requestBuilder; + // If first time, get the token + if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { + updateAccessToken(template); } - - public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); - - switch(flow) { - case accessCode: - case implicit: - tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); - break; - case password: - tokenRequestBuilder.setGrantType(GrantType.PASSWORD); - break; - case application: - tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); - break; - default: - break; - } - authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + if (getAccessToken() != null) { + template.header("Authorization", "Bearer " + getAccessToken()); } + } - public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes); + private synchronized void updateAccessToken(RequestTemplate template) { + OAuth2AccessToken accessTokenResponse; + try { + accessTokenResponse = getOAuth2AccessToken(); + } catch (Exception e) { + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); } - - @Override - public void apply(RequestTemplate template) { - // If the request already have an authorization (eg. Basic auth), do nothing - if (template.headers().containsKey("Authorization")) { - return; - } - // If first time, get the token - if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { - updateAccessToken(template); - } - if (getAccessToken() != null) { - template.header("Authorization", "Bearer " + getAccessToken()); - } + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); + if (accessTokenListener != null) { + accessTokenListener.notify(accessTokenResponse); + } } + } - public synchronized void updateAccessToken(RequestTemplate template) { - OAuthJSONAccessTokenResponse accessTokenResponse; - try { - accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); - } catch (Exception e) { - throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); - } - if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { - setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); - if (accessTokenListener != null) { - accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); - } - } - } + abstract OAuth2AccessToken getOAuth2AccessToken(); - public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - this.accessTokenListener = accessTokenListener; - } + abstract OAuthFlow getFlow(); - public synchronized String getAccessToken() { - return accessToken; - } + public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } - public synchronized void setAccessToken(String accessToken, Long expiresIn) { - this.accessToken = accessToken; - this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; - } + public synchronized String getAccessToken() { + return accessToken; + } - public TokenRequestBuilder getTokenRequestBuilder() { - return tokenRequestBuilder; - } + public synchronized void setAccessToken(String accessToken, Integer expiresIn) { + this.accessToken = accessToken; + this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + } - public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { - this.tokenRequestBuilder = tokenRequestBuilder; - } - - public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { - return authenticationRequestBuilder; - } - - public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { - this.authenticationRequestBuilder = authenticationRequestBuilder; - } - - public OAuthClient getOauthClient() { - return oauthClient; - } - - public void setOauthClient(OAuthClient oauthClient) { - this.oauthClient = oauthClient; - } - - public void setOauthClient(Client client) { - this.oauthClient = new OAuthClient( new OAuthFeignClient(client)); - } - - public static class OAuthFeignClient implements HttpClient { - - private Client client; - - public OAuthFeignClient() { - this.client = new Client.Default(null, null); - } - - public OAuthFeignClient(Client client) { - this.client = client; - } - - public T execute(OAuthClientRequest request, Map headers, - String requestMethod, Class responseClass) - throws OAuthSystemException, OAuthProblemException { - - RequestTemplate req = new RequestTemplate() - .append(request.getLocationUri()) - .method(requestMethod) - .body(request.getBody()); - - for (Entry entry : headers.entrySet()) { - req.header(entry.getKey(), entry.getValue()); - } - Response feignResponse; - String body = ""; - try { - feignResponse = client.execute(req.request(), new Options()); - body = Util.toString(feignResponse.body().asReader()); - } catch (IOException e) { - throw new OAuthSystemException(e); - } - - String contentType = null; - Collection contentTypeHeader = feignResponse.headers().get("Content-Type"); - if(contentTypeHeader != null) { - contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";"); - } - - return OAuthClientResponseFactory.createCustomResponse( - body, - contentType, - feignResponse.status(), - responseClass - ); - } - - public void shutdown() { - // Nothing to do here - } - } -} +} \ No newline at end of file diff --git a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OauthClientCredentialsGrant.java b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OauthClientCredentialsGrant.java new file mode 100644 index 00000000000..a21c5a15ba2 --- /dev/null +++ b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OauthClientCredentialsGrant.java @@ -0,0 +1,39 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OauthClientCredentialsGrant extends OAuth { + + public OauthClientCredentialsGrant(String authorizationUrl, String tokenUrl, String scopes) { + super(authorizationUrl, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenClientCredentialsGrant(scopes); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.application; + } + + /** + * Configures the client credentials flow + * + * @param clientId + * @param clientSecret + */ + public void configure(String clientId, String clientSecret) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} diff --git a/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OauthPasswordGrant.java b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OauthPasswordGrant.java new file mode 100644 index 00000000000..dba4fb3a076 --- /dev/null +++ b/samples/client/petstore/java/feign-no-nullable/src/main/java/org/openapitools/client/auth/OauthPasswordGrant.java @@ -0,0 +1,48 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OauthPasswordGrant extends OAuth { + + private String username; + private String password; + + public OauthPasswordGrant(String tokenUrl, String scopes) { + super(null, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenPasswordGrant(username, password); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.password; + } + + /** + * Configures Oauth password grant flow + * Note: this flow is deprecated. + * + * @param username + * @param password + * @param clientId + * @param clientSecret + */ + public void configure(String username, String password, String clientId, String clientSecret) { + this.username = username; + this.password = password; + //TODO the clientId and secret are optional according with the RFC + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/feign/.openapi-generator/FILES b/samples/client/petstore/java/feign/.openapi-generator/FILES index 1e341310444..cd394fffa07 100644 --- a/samples/client/petstore/java/feign/.openapi-generator/FILES +++ b/samples/client/petstore/java/feign/.openapi-generator/FILES @@ -28,10 +28,13 @@ src/main/java/org/openapitools/client/api/PetApi.java 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/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/OAuthFlow.java +src/main/java/org/openapitools/client/auth/OauthClientCredentialsGrant.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/feign/README.md b/samples/client/petstore/java/feign/README.md index 646dfdc4e2b..fa5dd565da4 100644 --- a/samples/client/petstore/java/feign/README.md +++ b/samples/client/petstore/java/feign/README.md @@ -32,6 +32,41 @@ After the client library is installed/deployed, you can use it in your Maven pro ``` +And to use the api you can follow the examples bellow: + +```java + + //Set bearer token manually + ApiClient apiClient = new ApiClient("petstore_auth_client"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setAccessToken("TOKEN", 10000); + + //Use api key + ApiClient apiClient = new ApiClient("api_key", "API KEY"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + + //Use http basic authentication + ApiClient apiClient = new ApiClient("basicAuth"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setCredentials("username", "password"); + + //Oauth password + ApiClient apiClient = new ApiClient("oauth_password"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setOauthPassword("username", "password", "client_id", "client_secret"); + + //Oauth client credentials flow + ApiClient apiClient = new ApiClient("oauth_client_credentials"); + apiClient.setBasePath("https://localhost:8243/petstore/1/"); + apiClient.setClientCredentials("client_id", "client_secret"); + + PetApi petApi = apiClient.buildClient(PetApi.class); + Pet petById = petApi.getPetById(12345L); + + System.out.println(petById); + } +``` + ## Recommendation It's recommended to create an instance of `ApiClient` per thread in a multithreaded environment to avoid any potential issues. @@ -40,4 +75,3 @@ It's recommended to create an instance of `ApiClient` per thread in a multithrea - diff --git a/samples/client/petstore/java/feign/build.gradle b/samples/client/petstore/java/feign/build.gradle index 8e51bb4bfd9..637b0f9d649 100644 --- a/samples/client/petstore/java/feign/build.gradle +++ b/samples/client/petstore/java/feign/build.gradle @@ -33,8 +33,8 @@ if(hasProperty('target') && target == 'android') { targetSdkVersion 25 } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } // Rename the aar correctly @@ -79,8 +79,8 @@ if(hasProperty('target') && target == 'android') { apply plugin: 'java' apply plugin: 'maven' - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 install { repositories.mavenInstaller { @@ -103,7 +103,7 @@ ext { feign_version = "10.11" feign_form_version = "3.8.0" junit_version = "4.13.1" - oltu_version = "1.0.1" + scribejava_version = "8.0.0" } dependencies { @@ -118,7 +118,8 @@ dependencies { implementation "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version" implementation "org.openapitools:jackson-databind-nullable:$jackson_databind_nullable_version" implementation "com.github.joschi.jackson:jackson-datatype-threetenbp:$jackson_threetenbp_version" - implementation "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltu_version" + implementation "com.brsanthu:migbase64:2.2" + implementation "com.github.scribejava:scribejava-core:$scribejava_version" implementation "com.brsanthu:migbase64:2.2" implementation 'javax.annotation:javax.annotation-api:1.3.2' testImplementation "junit:junit:$junit_version" diff --git a/samples/client/petstore/java/feign/build.sbt b/samples/client/petstore/java/feign/build.sbt index 1af0ed0153a..a2783502176 100644 --- a/samples/client/petstore/java/feign/build.sbt +++ b/samples/client/petstore/java/feign/build.sbt @@ -19,7 +19,7 @@ lazy val root = (project in file(".")). "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.3" % "compile", "com.fasterxml.jackson.datatype" % "jackson-datatype-joda" % "2.9.10" % "compile", "com.github.joschi.jackson" % "jackson-datatype-threetenbp" % "2.9.10" % "compile", - "org.apache.oltu.oauth2" % "org.apache.oltu.oauth2.client" % "1.0.1" % "compile", + "com.github.scribejava" % "scribejava-core" % "8.0.0" % "compile", "com.brsanthu" % "migbase64" % "2.2" % "compile", "javax.annotation" % "javax.annotation-api" % "1.3.2" % "compile", "junit" % "junit" % "4.13.1" % "test", diff --git a/samples/client/petstore/java/feign/pom.xml b/samples/client/petstore/java/feign/pom.xml index b7a9b1f4be8..b3b36a2077a 100644 --- a/samples/client/petstore/java/feign/pom.xml +++ b/samples/client/petstore/java/feign/pom.xml @@ -154,7 +154,7 @@ 3.1.1 none - 1.7 + 1.8 @@ -262,15 +262,15 @@ jackson-databind-nullable ${jackson-databind-nullable-version} - - com.github.joschi.jackson - jackson-datatype-threetenbp - ${jackson-threetenbp-version} - - org.apache.oltu.oauth2 - org.apache.oltu.oauth2.client - ${oltu-version} + com.github.joschi.jackson + jackson-datatype-threetenbp + ${jackson-threetenbp-version} + + + com.github.scribejava + scribejava-core + ${scribejava-version} javax.annotation @@ -301,7 +301,7 @@ UTF-8 - 1.7 + 1.8 ${java.version} ${java.version} 1.5.24 @@ -314,6 +314,6 @@ 1.3.2 4.13.1 1.0.0 - 1.0.1 + 8.0.0 diff --git a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiClient.java index 4e256daf6b2..87d97bddee8 100644 --- a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/ApiClient.java @@ -2,9 +2,8 @@ package org.openapitools.client; import java.util.LinkedHashMap; import java.util.Map; - -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; +import java.util.logging.Level; +import java.util.logging.Logger; import org.threeten.bp.*; @@ -25,6 +24,8 @@ import org.openapitools.client.auth.OAuth.AccessTokenListener; @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public class ApiClient { + private static final Logger log = Logger.getLogger(ApiClient.class.getName()); + public interface Api {} protected ObjectMapper objectMapper; @@ -44,6 +45,7 @@ public class ApiClient { public ApiClient(String[] authNames) { this(); for(String authName : authNames) { + log.log(Level.FINE, "Creating authentication {0}", authName); RequestInterceptor auth; if ("api_key".equals(authName)) { auth = new ApiKeyAuth("header", "api_key"); @@ -52,7 +54,7 @@ public class ApiClient { } else if ("http_basic_test".equals(authName)) { auth = new HttpBasicAuth(); } else if ("petstore_auth".equals(authName)) { - auth = new OAuth(OAuthFlow.implicit, "http://petstore.swagger.io/api/oauth/dialog", "", "write:pets, read:pets"); + auth = buildOauthRequestInterceptor(OAuthFlow.implicit, "http://petstore.swagger.io/api/oauth/dialog", "", "write:pets, read:pets"); } else { throw new RuntimeException("auth name \"" + authName + "\" not found in available auth names"); } @@ -78,34 +80,6 @@ public class ApiClient { this.setApiKey(apiKey); } - /** - * Helper constructor for single basic auth or password oauth2 - * @param authName - * @param username - * @param password - */ - public ApiClient(String authName, String username, String password) { - this(authName); - this.setCredentials(username, password); - } - - /** - * Helper constructor for single password oauth2 - * @param authName - * @param clientId - * @param secret - * @param username - * @param password - */ - public ApiClient(String authName, String clientId, String secret, String username, String password) { - this(authName); - this.getTokenEndPoint() - .setClientId(clientId) - .setClientSecret(secret) - .setUsername(username) - .setPassword(password); - } - public String getBasePath() { return basePath; } @@ -150,10 +124,25 @@ public class ApiClient { return objectMapper; } + private RequestInterceptor buildOauthRequestInterceptor(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { + switch (flow) { + case password: + return new OauthPasswordGrant(tokenUrl, scopes); + case application: + return new OauthClientCredentialsGrant(authorizationUrl, tokenUrl, scopes); + default: + throw new RuntimeException("Oauth flow \"" + flow + "\" is not implemented"); + } + } + public ObjectMapper getObjectMapper(){ return objectMapper; } + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + /** * Creates a feign client for given API interface. * @@ -200,19 +189,13 @@ public class ApiClient { return contentTypes[0]; } - /** * Helper method to configure the bearer token. * @param bearerToken the bearer token. */ public void setBearerToken(String bearerToken) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBearerAuth) { - ((HttpBearerAuth) apiAuthorization).setBearerToken(bearerToken); - return; - } - } - throw new RuntimeException("No Bearer authentication configured!"); + HttpBearerAuth apiAuthorization = getAuthorization(HttpBearerAuth.class); + apiAuthorization.setBearerToken(bearerToken); } /** @@ -220,63 +203,38 @@ public class ApiClient { * @param apiKey API key */ public void setApiKey(String apiKey) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof ApiKeyAuth) { - ApiKeyAuth keyAuth = (ApiKeyAuth) apiAuthorization; - keyAuth.setApiKey(apiKey); - return ; - } - } - throw new RuntimeException("No API key authentication configured!"); + ApiKeyAuth apiAuthorization = getAuthorization(ApiKeyAuth.class); + apiAuthorization.setApiKey(apiKey); } /** - * Helper method to configure the username/password for basic auth or password OAuth + * Helper method to configure the username/password for basic auth * @param username Username * @param password Password */ public void setCredentials(String username, String password) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof HttpBasicAuth) { - HttpBasicAuth basicAuth = (HttpBasicAuth) apiAuthorization; - basicAuth.setCredentials(username, password); - return; - } - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder().setUsername(username).setPassword(password); - return; - } - } - throw new RuntimeException("No Basic authentication or OAuth configured!"); + HttpBasicAuth apiAuthorization = getAuthorization(HttpBasicAuth.class); + apiAuthorization.setCredentials(username, password); } /** - * Helper method to configure the token endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Token request builder + * Helper method to configure the client credentials for Oauth + * @param username Username + * @param password Password */ - public TokenRequestBuilder getTokenEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getTokenRequestBuilder(); - } - } - return null; + public void setClientCredentials(String clientId, String clientSecret) { + OauthClientCredentialsGrant authorization = getAuthorization(OauthClientCredentialsGrant.class); + authorization.configure(clientId, clientSecret); } /** - * Helper method to configure authorization endpoint of the first oauth found in the apiAuthorizations (there should be only one) - * @return Authentication request builder + * Helper method to configure the username/password for Oauth password grant + * @param username Username + * @param password Password */ - public AuthenticationRequestBuilder getAuthorizationEndPoint() { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - return oauth.getAuthenticationRequestBuilder(); - } - } - return null; + public void setOauthPassword(String username, String password, String clientId, String clientSecret) { + OauthPasswordGrant apiAuthorization = getAuthorization(OauthPasswordGrant.class); + apiAuthorization.configure(username, password, clientId, clientSecret); } /** @@ -284,14 +242,9 @@ public class ApiClient { * @param accessToken Access Token * @param expiresIn Validity period in seconds */ - public void setAccessToken(String accessToken, Long expiresIn) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.setAccessToken(accessToken, expiresIn); - return; - } - } + public void setAccessToken(String accessToken, Integer expiresIn) { + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.setAccessToken(accessToken, expiresIn); } /** @@ -301,19 +254,7 @@ public class ApiClient { * @param redirectURI Redirect URI */ public void configureAuthorizationFlow(String clientId, String clientSecret, String redirectURI) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.getTokenRequestBuilder() - .setClientId(clientId) - .setClientSecret(clientSecret) - .setRedirectURI(redirectURI); - oauth.getAuthenticationRequestBuilder() - .setClientId(clientId) - .setRedirectURI(redirectURI); - return; - } - } + throw new RuntimeException("Not implemented"); } /** @@ -321,13 +262,8 @@ public class ApiClient { * @param accessTokenListener Acesss token listener */ public void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - for(RequestInterceptor apiAuthorization : apiAuthorizations.values()) { - if (apiAuthorization instanceof OAuth) { - OAuth oauth = (OAuth) apiAuthorization; - oauth.registerAccessTokenListener(accessTokenListener); - return; - } - } + OAuth apiAuthorization = getAuthorization(OAuth.class); + apiAuthorization.registerAccessTokenListener(accessTokenListener); } /** @@ -352,4 +288,11 @@ public class ApiClient { feignBuilder.requestInterceptor(authorization); } + private T getAuthorization(Class type) { + return (T) apiAuthorizations.values() + .stream() + .filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass())) + .findFirst() + .orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!")); + } } diff --git a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java new file mode 100644 index 00000000000..80db21111f9 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/DefaultApi20Impl.java @@ -0,0 +1,47 @@ +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; + + protected DefaultApi20Impl(String authorizationBaseUrl, String accessTokenEndpoint) { + this.authorizationBaseUrl = authorizationBaseUrl; + this.accessTokenEndpoint = accessTokenEndpoint; + } + + @Override + public String getAccessTokenEndpoint() { + return accessTokenEndpoint; + } + + @Override + protected String getAuthorizationBaseUrl() { + return authorizationBaseUrl; + } + + @Override + public BearerSignature getBearerSignature() { + return BearerSignatureURIQueryParameter.instance(); + } + + @Override + public ClientAuthentication getClientAuthentication() { + return RequestBodyAuthenticationScheme.instance(); + } + + @Override + public TokenExtractor getAccessTokenExtractor() { + return OAuth2AccessTokenJsonExtractor.instance(); + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OAuth.java b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OAuth.java index f59ad4a94ba..d41eca7a0a5 100644 --- a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OAuth.java +++ b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OAuth.java @@ -1,198 +1,81 @@ package org.openapitools.client.auth; -import java.io.IOException; -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.oltu.oauth2.client.HttpClient; -import org.apache.oltu.oauth2.client.OAuthClient; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.AuthenticationRequestBuilder; -import org.apache.oltu.oauth2.client.request.OAuthClientRequest.TokenRequestBuilder; -import org.apache.oltu.oauth2.client.response.OAuthClientResponse; -import org.apache.oltu.oauth2.client.response.OAuthClientResponseFactory; -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 org.apache.oltu.oauth2.common.token.BasicOAuthToken; - -import feign.Client; +import com.github.scribejava.core.model.OAuth2AccessToken; +import com.github.scribejava.core.oauth.OAuth20Service; import feign.Request.HttpMethod; -import feign.Request.Options; import feign.RequestInterceptor; import feign.RequestTemplate; -import feign.Response; import feign.RetryableException; -import feign.Util; -import org.openapitools.client.StringUtil; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public abstract class OAuth implements RequestInterceptor { -public class OAuth implements RequestInterceptor { + static final int MILLIS_PER_SECOND = 1000; - static final int MILLIS_PER_SECOND = 1000; + public interface AccessTokenListener { + void notify(OAuth2AccessToken token); + } - public interface AccessTokenListener { - void notify(BasicOAuthToken token); + private volatile String accessToken; + private Long expirationTimeMillis; + private AccessTokenListener accessTokenListener; + + protected OAuth20Service service; + protected String scopes; + protected String authorizationUrl; + protected String tokenUrl; + + public OAuth(String authorizationUrl, String tokenUrl, String scopes) { + this.scopes = scopes; + this.authorizationUrl = authorizationUrl; + this.tokenUrl = tokenUrl; + } + + @Override + public void apply(RequestTemplate template) { + // If the request already have an authorization (eg. Basic auth), do nothing + if (template.headers().containsKey("Authorization")) { + return; } - - private volatile String accessToken; - private Long expirationTimeMillis; - private OAuthClient oauthClient; - private TokenRequestBuilder tokenRequestBuilder; - private AuthenticationRequestBuilder authenticationRequestBuilder; - private AccessTokenListener accessTokenListener; - - public OAuth(Client client, TokenRequestBuilder requestBuilder) { - this.oauthClient = new OAuthClient(new OAuthFeignClient(client)); - this.tokenRequestBuilder = requestBuilder; + // If first time, get the token + if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { + updateAccessToken(template); } - - public OAuth(Client client, OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(client, OAuthClientRequest.tokenLocation(tokenUrl).setScope(scopes)); - - switch(flow) { - case accessCode: - case implicit: - tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE); - break; - case password: - tokenRequestBuilder.setGrantType(GrantType.PASSWORD); - break; - case application: - tokenRequestBuilder.setGrantType(GrantType.CLIENT_CREDENTIALS); - break; - default: - break; - } - authenticationRequestBuilder = OAuthClientRequest.authorizationLocation(authorizationUrl); + if (getAccessToken() != null) { + template.header("Authorization", "Bearer " + getAccessToken()); } + } - public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) { - this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes); + private synchronized void updateAccessToken(RequestTemplate template) { + OAuth2AccessToken accessTokenResponse; + try { + accessTokenResponse = getOAuth2AccessToken(); + } catch (Exception e) { + throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); } - - @Override - public void apply(RequestTemplate template) { - // If the request already have an authorization (eg. Basic auth), do nothing - if (template.headers().containsKey("Authorization")) { - return; - } - // If first time, get the token - if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) { - updateAccessToken(template); - } - if (getAccessToken() != null) { - template.header("Authorization", "Bearer " + getAccessToken()); - } + if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { + setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); + if (accessTokenListener != null) { + accessTokenListener.notify(accessTokenResponse); + } } + } - public synchronized void updateAccessToken(RequestTemplate template) { - OAuthJSONAccessTokenResponse accessTokenResponse; - try { - accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage()); - } catch (Exception e) { - throw new RetryableException(0, e.getMessage(), HttpMethod.POST, e, null, template.request()); - } - if (accessTokenResponse != null && accessTokenResponse.getAccessToken() != null) { - setAccessToken(accessTokenResponse.getAccessToken(), accessTokenResponse.getExpiresIn()); - if (accessTokenListener != null) { - accessTokenListener.notify((BasicOAuthToken) accessTokenResponse.getOAuthToken()); - } - } - } + abstract OAuth2AccessToken getOAuth2AccessToken(); - public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { - this.accessTokenListener = accessTokenListener; - } + abstract OAuthFlow getFlow(); - public synchronized String getAccessToken() { - return accessToken; - } + public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) { + this.accessTokenListener = accessTokenListener; + } - public synchronized void setAccessToken(String accessToken, Long expiresIn) { - this.accessToken = accessToken; - this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; - } + public synchronized String getAccessToken() { + return accessToken; + } - public TokenRequestBuilder getTokenRequestBuilder() { - return tokenRequestBuilder; - } + public synchronized void setAccessToken(String accessToken, Integer expiresIn) { + this.accessToken = accessToken; + this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND; + } - public void setTokenRequestBuilder(TokenRequestBuilder tokenRequestBuilder) { - this.tokenRequestBuilder = tokenRequestBuilder; - } - - public AuthenticationRequestBuilder getAuthenticationRequestBuilder() { - return authenticationRequestBuilder; - } - - public void setAuthenticationRequestBuilder(AuthenticationRequestBuilder authenticationRequestBuilder) { - this.authenticationRequestBuilder = authenticationRequestBuilder; - } - - public OAuthClient getOauthClient() { - return oauthClient; - } - - public void setOauthClient(OAuthClient oauthClient) { - this.oauthClient = oauthClient; - } - - public void setOauthClient(Client client) { - this.oauthClient = new OAuthClient( new OAuthFeignClient(client)); - } - - public static class OAuthFeignClient implements HttpClient { - - private Client client; - - public OAuthFeignClient() { - this.client = new Client.Default(null, null); - } - - public OAuthFeignClient(Client client) { - this.client = client; - } - - public T execute(OAuthClientRequest request, Map headers, - String requestMethod, Class responseClass) - throws OAuthSystemException, OAuthProblemException { - - RequestTemplate req = new RequestTemplate() - .append(request.getLocationUri()) - .method(requestMethod) - .body(request.getBody()); - - for (Entry entry : headers.entrySet()) { - req.header(entry.getKey(), entry.getValue()); - } - Response feignResponse; - String body = ""; - try { - feignResponse = client.execute(req.request(), new Options()); - body = Util.toString(feignResponse.body().asReader()); - } catch (IOException e) { - throw new OAuthSystemException(e); - } - - String contentType = null; - Collection contentTypeHeader = feignResponse.headers().get("Content-Type"); - if(contentTypeHeader != null) { - contentType = StringUtil.join(contentTypeHeader.toArray(new String[0]), ";"); - } - - return OAuthClientResponseFactory.createCustomResponse( - body, - contentType, - feignResponse.status(), - responseClass - ); - } - - public void shutdown() { - // Nothing to do here - } - } -} +} \ No newline at end of file diff --git a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OauthClientCredentialsGrant.java b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OauthClientCredentialsGrant.java new file mode 100644 index 00000000000..a21c5a15ba2 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OauthClientCredentialsGrant.java @@ -0,0 +1,39 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OauthClientCredentialsGrant extends OAuth { + + public OauthClientCredentialsGrant(String authorizationUrl, String tokenUrl, String scopes) { + super(authorizationUrl, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenClientCredentialsGrant(scopes); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.application; + } + + /** + * Configures the client credentials flow + * + * @param clientId + * @param clientSecret + */ + public void configure(String clientId, String clientSecret) { + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} diff --git a/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OauthPasswordGrant.java b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OauthPasswordGrant.java new file mode 100644 index 00000000000..dba4fb3a076 --- /dev/null +++ b/samples/client/petstore/java/feign/src/main/java/org/openapitools/client/auth/OauthPasswordGrant.java @@ -0,0 +1,48 @@ +package org.openapitools.client.auth; + +import com.github.scribejava.core.builder.ServiceBuilder; +import com.github.scribejava.core.model.OAuth2AccessToken; + +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class OauthPasswordGrant extends OAuth { + + private String username; + private String password; + + public OauthPasswordGrant(String tokenUrl, String scopes) { + super(null, tokenUrl, scopes); + } + + @Override + protected OAuth2AccessToken getOAuth2AccessToken() { + try { + return service.getAccessTokenPasswordGrant(username, password); + } catch (Exception e) { + throw new RuntimeException("Failed to get oauth token", e); + } + } + + @Override + protected OAuthFlow getFlow() { + return OAuthFlow.password; + } + + /** + * Configures Oauth password grant flow + * Note: this flow is deprecated. + * + * @param username + * @param password + * @param clientId + * @param clientSecret + */ + public void configure(String username, String password, String clientId, String clientSecret) { + this.username = username; + this.password = password; + //TODO the clientId and secret are optional according with the RFC + service = new ServiceBuilder(clientId) + .apiSecret(clientSecret) + .defaultScope(scopes) + .build(new DefaultApi20Impl(authorizationUrl, tokenUrl)); + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/jersey1/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/jersey1/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/jersey1/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/jersey1/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/okhttp-gson-dynamicOperations/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/okhttp-gson-parcelableModel/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/resteasy/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/resteasy/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/resteasy/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/resteasy/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/retrofit2/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/retrofit2/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/retrofit2/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/retrofit2/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/retrofit2rx2/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/retrofit2rx2/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/retrofit2rx2/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/retrofit2rx2/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/client/petstore/java/retrofit2rx3/src/main/java/org/openapitools/client/auth/OAuthFlow.java b/samples/client/petstore/java/retrofit2rx3/src/main/java/org/openapitools/client/auth/OAuthFlow.java index b2d11ff0c4f..75c2a0c9740 100644 --- a/samples/client/petstore/java/retrofit2rx3/src/main/java/org/openapitools/client/auth/OAuthFlow.java +++ b/samples/client/petstore/java/retrofit2rx3/src/main/java/org/openapitools/client/auth/OAuthFlow.java @@ -13,6 +13,10 @@ package org.openapitools.client.auth; +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public enum OAuthFlow { - accessCode, implicit, password, application + accessCode, //called authorizationCode in OpenAPI 3.0 + implicit, + password, + application //called clientCredentials in OpenAPI 3.0 } diff --git a/samples/server/petstore/java-undertow/dependency-reduced-pom.xml b/samples/server/petstore/java-undertow/dependency-reduced-pom.xml index 2c176c4af89..f86a92f3f0a 100644 --- a/samples/server/petstore/java-undertow/dependency-reduced-pom.xml +++ b/samples/server/petstore/java-undertow/dependency-reduced-pom.xml @@ -1,131 +1,131 @@ - - - - oss-parent - org.sonatype.oss - 5 - ../pom.xml/pom.xml - - 4.0.0 - org.openapitools - openapi-undertow-server - openapi-undertow-server - 1.0.0 - - install - target - ${project.artifactId}-${project.version} - - - maven-enforcer-plugin - 3.0.0-M1 - - - enforce-maven - - enforce - - - - - 2.2.0 - - - - - - - - maven-shade-plugin - 2.4.3 - - - package - - shade - - - - - - - - - - - maven-jar-plugin - 2.6 - - - - com.networknt.server.Server - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.4.0 - - java - - -jar - target/${project.build.finalName}.jar - - - - - - - - - sonatype-snapshots - https://oss.sonatype.org/content/repositories/snapshots - - - - - junit - junit - 4.13 - test - - - hamcrest-core - org.hamcrest - - - - - org.apache.httpcomponents - httpclient - 4.5.2 - test - - - - 4.1.2 - 2.9.10.4 - 2.2.0 - 1.10 - 3.1.2 - UTF-8 - 1.2 - 4.5.2 - 1.4.0.Final - 0.5.2 - 2.6 - 1.8 - 2.9.10 - 0.1.1 - 1.5.10 - 2.1.0-beta.124 - 1.7.21 - 2.5 - 1.1.7 - 4.13 - 4.5.3 - - - + + + + oss-parent + org.sonatype.oss + 5 + ../pom.xml/pom.xml + + 4.0.0 + org.openapitools + openapi-undertow-server + openapi-undertow-server + 1.0.0 + + install + target + ${project.artifactId}-${project.version} + + + maven-enforcer-plugin + 3.0.0-M1 + + + enforce-maven + + enforce + + + + + 2.2.0 + + + + + + + + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + + + + + + + maven-jar-plugin + 2.6 + + + + com.networknt.server.Server + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + java + + -jar + target/${project.build.finalName}.jar + + + + + + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + + + + junit + junit + 4.13 + test + + + hamcrest-core + org.hamcrest + + + + + org.apache.httpcomponents + httpclient + 4.5.2 + test + + + + 4.1.2 + 2.9.10.4 + 2.2.0 + 1.10 + 3.1.2 + UTF-8 + 1.2 + 4.5.2 + 1.4.0.Final + 0.5.2 + 2.6 + 1.8 + 2.9.10 + 0.1.1 + 1.5.10 + 2.1.0-beta.124 + 1.7.21 + 2.5 + 1.1.7 + 4.13 + 4.5.3 + + +