[JAVA][Feign] Replace Apache oltu with scribejava (#8318)

* - Replace apache oltu with scribejava
- Implement the following authentication methods
  - ApiKey header
  - HTTP basic authentication
  - Oauth client credentials flow
  - Oauth Implicit flow
  - Oauth Pasword (deprecated)

* Create class hierarchy for Oauth flows implementation

* Add instructions of how to use the ApiClient to Readme.md

* Update samples

* Remove support for java 6 and 7

* Remove java 6 and 7 support from gradle

* Format pom.xml

* Remove empty line

* Update samples

* Remove oltu dependency from build.gradle and build.sbt.
Replace oltu with ScribeJava

Update samples

* Update samples

* Update samples
This commit is contained in:
Hugo Alves 2021-01-19 04:41:25 +00:00 committed by GitHub
parent 6e4c1307a7
commit ede2a2316c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 1208 additions and 1211 deletions

View File

@ -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"));

View File

@ -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
}

View File

@ -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 extends RequestInterceptor> T getAuthorization(Class<T> type) {
return (T) apiAuthorizations.values()
.stream()
.filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass()))
.findFirst()
.orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!"));
}
}

View File

@ -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}}

View File

@ -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<OAuth2AccessToken> getAccessTokenExtractor() {
return OAuth2AccessTokenJsonExtractor.instance();
}
}

View File

@ -1,76 +1,34 @@
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;
public class OAuth implements RequestInterceptor {
{{>generatedAnnotation}}
public abstract class OAuth implements RequestInterceptor {
static final int MILLIS_PER_SECOND = 1000;
public interface AccessTokenListener {
void notify(BasicOAuthToken token);
void notify(OAuth2AccessToken token);
}
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;
}
protected OAuth20Service service;
protected String scopes;
protected String authorizationUrl;
protected String tokenUrl;
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);
}
public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes);
public OAuth(String authorizationUrl, String tokenUrl, String scopes) {
this.scopes = scopes;
this.authorizationUrl = authorizationUrl;
this.tokenUrl = tokenUrl;
}
@Override
@ -88,21 +46,25 @@ public class OAuth implements RequestInterceptor {
}
}
public synchronized void updateAccessToken(RequestTemplate template) {
OAuthJSONAccessTokenResponse accessTokenResponse;
private synchronized void updateAccessToken(RequestTemplate template) {
OAuth2AccessToken accessTokenResponse;
try {
accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
accessTokenResponse = getOAuth2AccessToken();
} 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());
accessTokenListener.notify(accessTokenResponse);
}
}
}
abstract OAuth2AccessToken getOAuth2AccessToken();
abstract OAuthFlow getFlow();
public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
this.accessTokenListener = accessTokenListener;
}
@ -111,88 +73,9 @@ public class OAuth implements RequestInterceptor {
return accessToken;
}
public synchronized void setAccessToken(String accessToken, Long expiresIn) {
public synchronized void setAccessToken(String accessToken, Integer expiresIn) {
this.accessToken = accessToken;
this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
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 extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
RequestTemplate req = new RequestTemplate()
.append(request.getLocationUri())
.method(requestMethod)
.body(request.getBody());
for (Entry<String, String> 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<String> 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
}
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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"

View File

@ -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",

View File

@ -161,17 +161,7 @@
<version>3.1.1</version>
<configuration>
<doclint>none</doclint>
{{#supportJava6}}
<source>1.6</source>
{{/supportJava6}}
{{^supportJava6}}
{{#java8}}
<source>1.8</source>
{{/java8}}
{{^java8}}
<source>1.7</source>
{{/java8}}
{{/supportJava6}}
</configuration>
<executions>
<execution>
@ -282,14 +272,12 @@
</dependency>
{{/openApiNullable}}
{{#withXml}}
<!-- XML Support -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson-version}</version>
</dependency>
{{/withXml}}
{{#joda}}
<dependency>
@ -313,9 +301,9 @@
</dependency>
{{/threetenbp}}
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>${oltu-version}</version>
<groupId>com.github.scribejava</groupId>
<artifactId>scribejava-core</artifactId>
<version>${scribejava-version}</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
@ -346,7 +334,7 @@
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>{{#supportJava6}}1.6{{/supportJava6}}{{^supportJava6}}{{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}}{{/supportJava6}}</java.version>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<swagger-annotations-version>1.5.24</swagger-annotations-version>
@ -363,6 +351,6 @@
<javax-annotation-version>1.3.2</javax-annotation-version>
<junit-version>4.13.1</junit-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<oltu-version>1.0.1</oltu-version>
<scribejava-version>8.0.0</scribejava-version>
</properties>
</project>

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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",

View File

@ -154,7 +154,7 @@
<version>3.1.1</version>
<configuration>
<doclint>none</doclint>
<source>1.7</source>
<source>1.8</source>
</configuration>
<executions>
<execution>
@ -263,9 +263,9 @@
<version>${jackson-threetenbp-version}</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>${oltu-version}</version>
<groupId>com.github.scribejava</groupId>
<artifactId>scribejava-core</artifactId>
<version>${scribejava-version}</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
@ -296,7 +296,7 @@
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<swagger-annotations-version>1.5.24</swagger-annotations-version>
@ -308,6 +308,6 @@
<javax-annotation-version>1.3.2</javax-annotation-version>
<junit-version>4.13.1</junit-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<oltu-version>1.0.1</oltu-version>
<scribejava-version>8.0.0</scribejava-version>
</properties>
</project>

View File

@ -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 extends RequestInterceptor> T getAuthorization(Class<T> type) {
return (T) apiAuthorizations.values()
.stream()
.filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass()))
.findFirst()
.orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!"));
}
}

View File

@ -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<OAuth2AccessToken> getAccessTokenExtractor() {
return OAuth2AccessTokenJsonExtractor.instance();
}
}

View File

@ -1,76 +1,34 @@
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;
public class OAuth implements RequestInterceptor {
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
public abstract class OAuth implements RequestInterceptor {
static final int MILLIS_PER_SECOND = 1000;
public interface AccessTokenListener {
void notify(BasicOAuthToken token);
void notify(OAuth2AccessToken token);
}
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;
}
protected OAuth20Service service;
protected String scopes;
protected String authorizationUrl;
protected String tokenUrl;
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);
}
public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes);
public OAuth(String authorizationUrl, String tokenUrl, String scopes) {
this.scopes = scopes;
this.authorizationUrl = authorizationUrl;
this.tokenUrl = tokenUrl;
}
@Override
@ -88,21 +46,25 @@ public class OAuth implements RequestInterceptor {
}
}
public synchronized void updateAccessToken(RequestTemplate template) {
OAuthJSONAccessTokenResponse accessTokenResponse;
private synchronized void updateAccessToken(RequestTemplate template) {
OAuth2AccessToken accessTokenResponse;
try {
accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
accessTokenResponse = getOAuth2AccessToken();
} 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());
accessTokenListener.notify(accessTokenResponse);
}
}
}
abstract OAuth2AccessToken getOAuth2AccessToken();
abstract OAuthFlow getFlow();
public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
this.accessTokenListener = accessTokenListener;
}
@ -111,88 +73,9 @@ public class OAuth implements RequestInterceptor {
return accessToken;
}
public synchronized void setAccessToken(String accessToken, Long expiresIn) {
public synchronized void setAccessToken(String accessToken, Integer expiresIn) {
this.accessToken = accessToken;
this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
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 extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
RequestTemplate req = new RequestTemplate()
.append(request.getLocationUri())
.method(requestMethod)
.body(request.getBody());
for (Entry<String, String> 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<String> 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
}
}
}

View File

@ -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
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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",

View File

@ -154,7 +154,7 @@
<version>3.1.1</version>
<configuration>
<doclint>none</doclint>
<source>1.7</source>
<source>1.8</source>
</configuration>
<executions>
<execution>
@ -268,9 +268,9 @@
<version>${jackson-threetenbp-version}</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>${oltu-version}</version>
<groupId>com.github.scribejava</groupId>
<artifactId>scribejava-core</artifactId>
<version>${scribejava-version}</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
@ -301,7 +301,7 @@
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<swagger-annotations-version>1.5.24</swagger-annotations-version>
@ -314,6 +314,6 @@
<javax-annotation-version>1.3.2</javax-annotation-version>
<junit-version>4.13.1</junit-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<oltu-version>1.0.1</oltu-version>
<scribejava-version>8.0.0</scribejava-version>
</properties>
</project>

View File

@ -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 extends RequestInterceptor> T getAuthorization(Class<T> type) {
return (T) apiAuthorizations.values()
.stream()
.filter(requestInterceptor -> type.isAssignableFrom(requestInterceptor.getClass()))
.findFirst()
.orElseThrow(() -> new RuntimeException("No Oauth authentication or OAuth configured!"));
}
}

View File

@ -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<OAuth2AccessToken> getAccessTokenExtractor() {
return OAuth2AccessTokenJsonExtractor.instance();
}
}

View File

@ -1,76 +1,34 @@
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;
public class OAuth implements RequestInterceptor {
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen")
public abstract class OAuth implements RequestInterceptor {
static final int MILLIS_PER_SECOND = 1000;
public interface AccessTokenListener {
void notify(BasicOAuthToken token);
void notify(OAuth2AccessToken token);
}
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;
}
protected OAuth20Service service;
protected String scopes;
protected String authorizationUrl;
protected String tokenUrl;
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);
}
public OAuth(OAuthFlow flow, String authorizationUrl, String tokenUrl, String scopes) {
this(new Client.Default(null, null), flow, authorizationUrl, tokenUrl, scopes);
public OAuth(String authorizationUrl, String tokenUrl, String scopes) {
this.scopes = scopes;
this.authorizationUrl = authorizationUrl;
this.tokenUrl = tokenUrl;
}
@Override
@ -88,21 +46,25 @@ public class OAuth implements RequestInterceptor {
}
}
public synchronized void updateAccessToken(RequestTemplate template) {
OAuthJSONAccessTokenResponse accessTokenResponse;
private synchronized void updateAccessToken(RequestTemplate template) {
OAuth2AccessToken accessTokenResponse;
try {
accessTokenResponse = oauthClient.accessToken(tokenRequestBuilder.buildBodyMessage());
accessTokenResponse = getOAuth2AccessToken();
} 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());
accessTokenListener.notify(accessTokenResponse);
}
}
}
abstract OAuth2AccessToken getOAuth2AccessToken();
abstract OAuthFlow getFlow();
public synchronized void registerAccessTokenListener(AccessTokenListener accessTokenListener) {
this.accessTokenListener = accessTokenListener;
}
@ -111,88 +73,9 @@ public class OAuth implements RequestInterceptor {
return accessToken;
}
public synchronized void setAccessToken(String accessToken, Long expiresIn) {
public synchronized void setAccessToken(String accessToken, Integer expiresIn) {
this.accessToken = accessToken;
this.expirationTimeMillis = expiresIn == null ? null : System.currentTimeMillis() + expiresIn * MILLIS_PER_SECOND;
}
public TokenRequestBuilder getTokenRequestBuilder() {
return tokenRequestBuilder;
}
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 extends OAuthClientResponse> T execute(OAuthClientRequest request, Map<String, String> headers,
String requestMethod, Class<T> responseClass)
throws OAuthSystemException, OAuthProblemException {
RequestTemplate req = new RequestTemplate()
.append(request.getLocationUri())
.method(requestMethod)
.body(request.getBody());
for (Entry<String, String> 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<String> 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
}
}
}

View File

@ -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
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}