From e77f9ea783bcdc8796cca46296f0e7016fc01b86 Mon Sep 17 00:00:00 2001 From: Dennis Melzer Date: Thu, 13 Jul 2023 02:35:39 +0200 Subject: [PATCH] Add new OAuth2RequestInterceptor to remove deprecated open feign classes (#16011) * Add new OAuth2RequestInterceptor to remove deprecated open feign classes * Add override * Add version * Add older version * Update docs * Fix issue with multiple security schemes * Move cli option to spring code gen * Fix documentation options * Remove resource folder * Fix duplicate annotation * Add an enable flag * Remove generator setting * Revert codgen changes * Revert config generator changes --- docs/generators/java-camel.md | 1 + docs/generators/spring.md | 1 + .../codegen/languages/SpringCodegen.java | 33 +++- .../spring-cloud/clientConfiguration.mustache | 158 ++++++++---------- .../clientPropertiesConfiguration.mustache | 18 ++ .../oauth2ClientProperties.mustache | 25 +++ .../libraries/spring-cloud/pom-sb3.mustache | 6 +- .../libraries/spring-cloud/pom.mustache | 6 +- .../petstore/spring-cloud-date-time/pom.xml | 6 +- .../.openapi-generator/FILES | 2 + .../spring-cloud-feign-without-url/pom.xml | 6 +- .../configuration/ClientConfiguration.java | 83 ++++++--- .../ClientPropertiesConfiguration.java | 10 ++ .../main/resources/oauth2-client.properties | 5 + .../client/petstore/spring-cloud-tags/pom.xml | 6 +- .../spring-cloud/.openapi-generator/FILES | 2 + samples/client/petstore/spring-cloud/pom.xml | 6 +- .../configuration/ClientConfiguration.java | 83 ++++++--- .../ClientPropertiesConfiguration.java | 10 ++ .../main/resources/oauth2-client.properties | 5 + .../.openapi-generator/FILES | 2 + .../spring-cloud-3-with-optional/pom.xml | 6 +- .../configuration/ClientConfiguration.java | 83 ++++++--- .../ClientPropertiesConfiguration.java | 10 ++ .../main/resources/oauth2-client.properties | 5 + .../spring-cloud-3/.openapi-generator/FILES | 2 + .../client/petstore/spring-cloud-3/pom.xml | 6 +- .../configuration/ClientConfiguration.java | 83 ++++++--- .../ClientPropertiesConfiguration.java | 10 ++ .../main/resources/oauth2-client.properties | 5 + .../.openapi-generator/FILES | 2 + .../petstore/spring-cloud-async/pom.xml | 6 +- .../configuration/ClientConfiguration.java | 83 ++++++--- .../ClientPropertiesConfiguration.java | 10 ++ .../main/resources/oauth2-client.properties | 5 + .../petstore/spring-cloud-date-time/pom.xml | 6 +- .../spring-cloud-oas3-fakeapi/pom.xml | 6 +- .../.openapi-generator/FILES | 2 + .../spring-cloud-spring-pageable/pom.xml | 6 +- .../configuration/ClientConfiguration.java | 83 ++++++--- .../ClientPropertiesConfiguration.java | 10 ++ .../main/resources/oauth2-client.properties | 5 + .../client/petstore/spring-cloud/pom.xml | 6 +- 43 files changed, 634 insertions(+), 280 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientPropertiesConfiguration.mustache create mode 100644 modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/oauth2ClientProperties.mustache create mode 100644 samples/client/petstore/spring-cloud-feign-without-url/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java create mode 100644 samples/client/petstore/spring-cloud-feign-without-url/src/main/resources/oauth2-client.properties create mode 100644 samples/client/petstore/spring-cloud/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java create mode 100644 samples/client/petstore/spring-cloud/src/main/resources/oauth2-client.properties create mode 100644 samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java create mode 100644 samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/resources/oauth2-client.properties create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java create mode 100644 samples/openapi3/client/petstore/spring-cloud-3/src/main/resources/oauth2-client.properties create mode 100644 samples/openapi3/client/petstore/spring-cloud-async/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java create mode 100644 samples/openapi3/client/petstore/spring-cloud-async/src/main/resources/oauth2-client.properties create mode 100644 samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java create mode 100644 samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/resources/oauth2-client.properties diff --git a/docs/generators/java-camel.md b/docs/generators/java-camel.md index 90a2971c9948..850f5893ddbe 100644 --- a/docs/generators/java-camel.md +++ b/docs/generators/java-camel.md @@ -77,6 +77,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |reactive|wrap responses in Mono/Flux Reactor types (spring-boot only)| |false| |requestMappingMode|Where to generate the class level @RequestMapping annotation.|
**api_interface**
Generate the @RequestMapping annotation on the generated Api Interface.
**controller**
Generate the @RequestMapping annotation on the generated Api Controller Implementation.
**none**
Do not add a class level @RequestMapping annotation.
|controller| +|resourceFolder|resource folder for generated resources| |src/main/resources| |responseWrapper|wrap the responses in given type (Future, Callable, CompletableFuture,ListenableFuture, DeferredResult, RxObservable, RxSingle or fully qualified type)| |null| |returnSuccessCode|Generated server returns 2xx code| |false| |scmConnection|SCM connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git| diff --git a/docs/generators/spring.md b/docs/generators/spring.md index 132e2aaad63b..56213442d50c 100644 --- a/docs/generators/spring.md +++ b/docs/generators/spring.md @@ -70,6 +70,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |reactive|wrap responses in Mono/Flux Reactor types (spring-boot only)| |false| |requestMappingMode|Where to generate the class level @RequestMapping annotation.|
**api_interface**
Generate the @RequestMapping annotation on the generated Api Interface.
**controller**
Generate the @RequestMapping annotation on the generated Api Controller Implementation.
**none**
Do not add a class level @RequestMapping annotation.
|controller| +|resourceFolder|resource folder for generated resources| |src/main/resources| |responseWrapper|wrap the responses in given type (Future, Callable, CompletableFuture,ListenableFuture, DeferredResult, RxObservable, RxSingle or fully qualified type)| |null| |returnSuccessCode|Generated server returns 2xx code| |false| |scmConnection|SCM connection in generated pom.xml| |scm:git:git@github.com:openapitools/openapi-generator.git| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index 7c471653f689..6db6ad2903ed 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -77,6 +77,7 @@ public class SpringCodegen extends AbstractJavaCodegen implements BeanValidationFeatures, PerformBeanValidationFeatures, OptionalFeatures, SwaggerUIFeatures { private final Logger LOGGER = LoggerFactory.getLogger(SpringCodegen.class); + public static final String TITLE = "title"; public static final String SERVER_PORT = "serverPort"; public static final String CONFIG_PACKAGE = "configPackage"; @@ -90,6 +91,9 @@ public class SpringCodegen extends AbstractJavaCodegen public static final String SKIP_DEFAULT_INTERFACE = "skipDefaultInterface"; public static final String GENERATE_CONSTRUCTOR_WITH_REQUIRED_ARGS = "generatedConstructorWithRequiredArgs"; + public static final String RESOURCE_FOLDER = "resourceFolder"; + public static final String RESOURCE_FOLDER_DESC = "resource folder for generated resources"; + public static final String ASYNC = "async"; public static final String REACTIVE = "reactive"; public static final String RESPONSE_WRAPPER = "responseWrapper"; @@ -131,6 +135,8 @@ public class SpringCodegen extends AbstractJavaCodegen protected String title = "OpenAPI Spring"; protected String configPackage = "org.openapitools.configuration"; protected String basePackage = "org.openapitools"; + protected String resourceFolder = projectFolder + "/resources"; + protected boolean interfaceOnly = false; protected boolean useFeignClientUrl = true; protected boolean delegatePattern = false; @@ -256,6 +262,7 @@ public class SpringCodegen extends AbstractJavaCodegen cliOptions.add(CliOption.newBoolean(GENERATE_CONSTRUCTOR_WITH_REQUIRED_ARGS, "Whether to generate constructors with required args for models", generatedConstructorWithRequiredArgs)); + cliOptions.add(new CliOption(RESOURCE_FOLDER, RESOURCE_FOLDER_DESC).defaultValue(this.getResourceFolder())); supportedLibraries.put(SPRING_BOOT, "Spring-boot Server application."); supportedLibraries.put(SPRING_CLOUD_LIBRARY, @@ -531,6 +538,11 @@ public class SpringCodegen extends AbstractJavaCodegen } writePropertyBack(USE_SPRING_BOOT3, isUseSpringBoot3()); + if (additionalProperties.containsKey(RESOURCE_FOLDER)) { + this.setResourceFolder((String) additionalProperties.get(RESOURCE_FOLDER)); + } + additionalProperties.put(RESOURCE_FOLDER, resourceFolder); + typeMapping.put("file", "org.springframework.core.io.Resource"); importMapping.put("org.springframework.core.io.Resource", "org.springframework.core.io.Resource"); @@ -575,9 +587,18 @@ public class SpringCodegen extends AbstractJavaCodegen "RFC3339DateFormat.java")); } if (SPRING_CLOUD_LIBRARY.equals(library)) { + supportingFiles.add(new SupportingFile("apiKeyRequestInterceptor.mustache", - (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), - "ApiKeyRequestInterceptor.java")); + (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), + "ApiKeyRequestInterceptor.java")); + + supportingFiles.add(new SupportingFile("oauth2ClientProperties.mustache", + resourceFolder, "oauth2-client.properties")); + + supportingFiles.add(new SupportingFile("clientPropertiesConfiguration.mustache", + (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), + "ClientPropertiesConfiguration.java")); + supportingFiles.add(new SupportingFile("clientConfiguration.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "ClientConfiguration.java")); @@ -1349,6 +1370,14 @@ public class SpringCodegen extends AbstractJavaCodegen return dataType.replace( "<", "<@Valid " ); } + public void setResourceFolder( String resourceFolder ) { + this.resourceFolder = resourceFolder; + } + + public String getResourceFolder() { + return resourceFolder; + } + // This should prevent, that the response data types not contains a @Valid annotation. // However, the side effect is that attributes with response as name are also affected. diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache index 6eb263c20b9c..b943d221f450 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache @@ -3,49 +3,39 @@ package {{configPackage}}; {{#authMethods}} {{#isBasicBasic}} import feign.auth.BasicAuthRequestInterceptor; -{{/isBasicBasic}} -{{#-first}} +{{^hasApiKeyMethods}} import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -{{/-first}} -{{#isOAuth}} -import org.springframework.boot.context.properties.ConfigurationProperties; -{{/isOAuth}} +{{/hasApiKeyMethods}} +{{/isBasicBasic}} {{/authMethods}} -import org.springframework.boot.context.properties.EnableConfigurationProperties; -{{#authMethods}} -{{#-first}} +{{#hasAuthMethods}} import org.springframework.context.annotation.Bean; -{{/-first}} -{{/authMethods}} +{{#hasApiKeyMethods}} +import org.springframework.beans.factory.annotation.Value; +{{/hasApiKeyMethods}} +{{#hasOAuthMethods}} +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + +{{/hasOAuthMethods}} +{{/hasAuthMethods}} import org.springframework.context.annotation.Configuration; -{{#authMethods}} -{{#isOAuth}} -{{#useSpringBoot3}} -import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; -{{/useSpringBoot3}} -{{^useSpringBoot3}} -import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor; -{{/useSpringBoot3}} -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -{{#isApplication}} -import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; -{{/isApplication}} -{{#isCode}} -import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; -{{/isCode}} -{{#isImplicit}} -import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; -{{/isImplicit}} -{{#isPassword}} -import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; -{{/isPassword}} -{{/isOAuth}} -{{/authMethods}} + @Configuration -@EnableConfigurationProperties public class ClientConfiguration { {{#authMethods}} @@ -75,63 +65,53 @@ public class ClientConfiguration { {{/isApiKey}} {{#isOAuth}} + private static final String CLIENT_PRINCIPAL_{{#lambda.uppercase}}{{{flow}}}{{/lambda.uppercase}} = "oauth2FeignClient"; + @Bean - @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") - public OAuth2FeignRequestInterceptor {{{name}}}RequestInterceptor(OAuth2ClientContext oAuth2ClientContext) { - return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, {{{name}}}ResourceDetails()); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}", name = "enabled", havingValue = "true" ) + public OAuth2RequestInterceptor {{{flow}}}OAuth2RequestInterceptor(final OAuth2AuthorizedClientManager {{{flow}}}AuthorizedClientManager ) { + return new OAuth2RequestInterceptor(OAuth2AuthorizeRequest.withClientRegistrationId("{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}") + .principal( new AnonymousAuthenticationToken( CLIENT_PRINCIPAL_{{#lambda.uppercase}}{{{flow}}}{{/lambda.uppercase}}, CLIENT_PRINCIPAL_{{#lambda.uppercase}}{{{flow}}}{{/lambda.uppercase}}, AuthorityUtils.createAuthorityList( "ROLE_ANONYMOUS" ) ) ) + .build(), {{{flow}}}AuthorizedClientManager ); } @Bean - @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") - public OAuth2ClientContext oAuth2ClientContext() { - return new DefaultOAuth2ClientContext(); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}", name = "enabled", havingValue = "true" ) + public OAuth2AuthorizedClientManager {{{flow}}}AuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService ) { + return new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService ); } - - {{#isCode}} - @Bean - @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") - @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}") - public AuthorizationCodeResourceDetails {{{name}}}ResourceDetails() { - AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); - details.setAccessTokenUri("{{{tokenUrl}}}"); - details.setUserAuthorizationUri("{{{authorizationUrl}}}"); - return details; - } - - {{/isCode}} - {{#isPassword}} - @Bean - @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") - @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}") - public ResourceOwnerPasswordResourceDetails {{{name}}}ResourceDetails() { - ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails(); - details.setAccessTokenUri("{{{tokenUrl}}}"); - return details; - } - - {{/isPassword}} - {{#isApplication}} - @Bean - @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") - @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}") - public ClientCredentialsResourceDetails {{{name}}}ResourceDetails() { - ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails(); - details.setAccessTokenUri("{{{tokenUrl}}}"); - return details; - } - - {{/isApplication}} - {{#isImplicit}} - @Bean - @ConditionalOnProperty("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}.client-id") - @ConfigurationProperties("{{#lambda.lowercase}}{{{title}}}{{/lambda.lowercase}}.security.{{{name}}}") - public ImplicitResourceDetails {{{name}}}ResourceDetails() { - ImplicitResourceDetails details = new ImplicitResourceDetails(); - details.setUserAuthorizationUri("{{{authorizationUrl}}}"); - return details; - } - - {{/isImplicit}} {{/isOAuth}} {{/authMethods}} +{{#hasOAuthMethods}} + public static class OAuth2RequestInterceptor implements RequestInterceptor { + + private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager; + private final OAuth2AuthorizeRequest oAuth2AuthorizeRequest; + + public OAuth2RequestInterceptor(OAuth2AuthorizeRequest oAuth2AuthorizeRequest,OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager){ + this.oAuth2AuthorizeRequest = oAuth2AuthorizeRequest; + this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager; + } + + @Override + public void apply( final RequestTemplate template ) { + template.header( HttpHeaders.AUTHORIZATION, getBearerToken() ); + } + + public OAuth2AccessToken getAccessToken() { + final OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest); + if (authorizedClient == null) { + throw new OAuth2AuthenticationException( "Client failed to authenticate"); + } + return authorizedClient.getAccessToken(); + } + + public String getBearerToken() { + final OAuth2AccessToken accessToken = getAccessToken(); + return String.format( "%s %s", accessToken.getTokenType().getValue(), accessToken.getTokenValue() ); + } + } +{{/hasOAuthMethods}} + } diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientPropertiesConfiguration.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientPropertiesConfiguration.mustache new file mode 100644 index 000000000000..5e8a06ccce04 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/clientPropertiesConfiguration.mustache @@ -0,0 +1,18 @@ +package {{configPackage}}; + +{{#authMethods}} + {{#isOAuth}} +import org.springframework.context.annotation.PropertySource; + {{/isOAuth}} +{{/authMethods}} +import org.springframework.context.annotation.Configuration; + +{{#hasAuthMethods}} + {{#hasOAuthMethods}} +@PropertySource( "classpath:/oauth2-client.properties" ) + {{/hasOAuthMethods}} +{{/hasAuthMethods}} +@Configuration +public class ClientPropertiesConfiguration { + +} diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/oauth2ClientProperties.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/oauth2ClientProperties.mustache new file mode 100644 index 000000000000..8e9f54d1fd47 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/oauth2ClientProperties.mustache @@ -0,0 +1,25 @@ +{{#authMethods}} +{{#isOAuth}} +spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.enabled=false +spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.client-id=set-{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}-client-id +{{#scopes}}{{#-first}}spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.scopes={{/-first}}{{scope}}{{^-last}},{{/-last}}{{/scopes}} + {{#isCode}} +spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.authorization-grant-type=authorization_code +spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.redirect-uri=set-{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}-redirect-uri +spring.security.oauth2.client.provider.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.token-uri={{{tokenUrl}}} +spring.security.oauth2.client.provider.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.authorization-uri={{{authorizationUrl}}} + {{/isCode}} + {{#isPassword}} +spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.authorization-grant-type=password +spring.security.oauth2.client.provider.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.token-uri={{{tokenUrl}}} + {{/isPassword}} + {{#isApplication}} +spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.authorization-grant-type=client_credentials +spring.security.oauth2.client.provider.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.token-uri={{{tokenUrl}}} + {{/isApplication}} + {{#isImplicit}} +spring.security.oauth2.client.registration.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.authorization-grant-type=implicit +spring.security.oauth2.client.provider.{{{name}}}{{#lambda.pascalcase}}{{{flow}}}{{/lambda.pascalcase}}.authorization-uri={{{authorizationUrl}}} + {{/isImplicit}} +{{/isOAuth}} +{{/authMethods}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache index cbee4693c6e0..1d394d941807 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom-sb3.mustache @@ -92,10 +92,10 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 + org.springframework.security + spring-security-oauth2-client {{^parentOverridden}} - 2.2.5.RELEASE + 6.1.1 {{/parentOverridden}} {{#withXml}} diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache index 5024e469a9d8..c0baca307de4 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache @@ -108,10 +108,10 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 + org.springframework.security + spring-security-oauth2-client {{^parentOverridden}} - 2.2.5.RELEASE + 5.7.8 {{/parentOverridden}} {{#withXml}} diff --git a/samples/client/petstore/spring-cloud-date-time/pom.xml b/samples/client/petstore/spring-cloud-date-time/pom.xml index 2440d30f3967..aab77c33a65b 100644 --- a/samples/client/petstore/spring-cloud-date-time/pom.xml +++ b/samples/client/petstore/spring-cloud-date-time/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype diff --git a/samples/client/petstore/spring-cloud-feign-without-url/.openapi-generator/FILES b/samples/client/petstore/spring-cloud-feign-without-url/.openapi-generator/FILES index 3510d2b2d276..553a884f54d0 100644 --- a/samples/client/petstore/spring-cloud-feign-without-url/.openapi-generator/FILES +++ b/samples/client/petstore/spring-cloud-feign-without-url/.openapi-generator/FILES @@ -8,9 +8,11 @@ src/main/java/org/openapitools/api/UserApi.java src/main/java/org/openapitools/api/UserApiClient.java src/main/java/org/openapitools/configuration/ApiKeyRequestInterceptor.java src/main/java/org/openapitools/configuration/ClientConfiguration.java +src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java src/main/java/org/openapitools/model/Category.java src/main/java/org/openapitools/model/ModelApiResponse.java src/main/java/org/openapitools/model/Order.java src/main/java/org/openapitools/model/Pet.java src/main/java/org/openapitools/model/Tag.java src/main/java/org/openapitools/model/User.java +src/main/resources/oauth2-client.properties diff --git a/samples/client/petstore/spring-cloud-feign-without-url/pom.xml b/samples/client/petstore/spring-cloud-feign-without-url/pom.xml index e893d0fa75f0..022cfd58ef9f 100644 --- a/samples/client/petstore/spring-cloud-feign-without-url/pom.xml +++ b/samples/client/petstore/spring-cloud-feign-without-url/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype diff --git a/samples/client/petstore/spring-cloud-feign-without-url/src/main/java/org/openapitools/configuration/ClientConfiguration.java b/samples/client/petstore/spring-cloud-feign-without-url/src/main/java/org/openapitools/configuration/ClientConfiguration.java index 49f1c66c11a7..0dc419b64b4f 100644 --- a/samples/client/petstore/spring-cloud-feign-without-url/src/main/java/org/openapitools/configuration/ClientConfiguration.java +++ b/samples/client/petstore/spring-cloud-feign-without-url/src/main/java/org/openapitools/configuration/ClientConfiguration.java @@ -1,41 +1,45 @@ package org.openapitools.configuration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + import org.springframework.context.annotation.Configuration; -import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; + @Configuration -@EnableConfigurationProperties public class ClientConfiguration { + private static final String CLIENT_PRINCIPAL_IMPLICIT = "oauth2FeignClient"; + @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2FeignRequestInterceptor petstoreAuthRequestInterceptor(OAuth2ClientContext oAuth2ClientContext) { - return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, petstoreAuthResourceDetails()); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2RequestInterceptor implicitOAuth2RequestInterceptor(final OAuth2AuthorizedClientManager implicitAuthorizedClientManager ) { + return new OAuth2RequestInterceptor(OAuth2AuthorizeRequest.withClientRegistrationId("petstoreAuthImplicit") + .principal( new AnonymousAuthenticationToken( CLIENT_PRINCIPAL_IMPLICIT, CLIENT_PRINCIPAL_IMPLICIT, AuthorityUtils.createAuthorityList( "ROLE_ANONYMOUS" ) ) ) + .build(), implicitAuthorizedClientManager ); } @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2ClientContext oAuth2ClientContext() { - return new DefaultOAuth2ClientContext(); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2AuthorizedClientManager implicitAuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService ) { + return new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService ); } - - @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - @ConfigurationProperties("openapipetstore.security.petstoreAuth") - public ImplicitResourceDetails petstoreAuthResourceDetails() { - ImplicitResourceDetails details = new ImplicitResourceDetails(); - details.setUserAuthorizationUri("http://petstore.swagger.io/api/oauth/dialog"); - return details; - } - @Value("${openapipetstore.security.apiKey.key:}") private String apiKeyKey; @@ -45,4 +49,33 @@ public class ClientConfiguration { return new ApiKeyRequestInterceptor("header", "api_key", this.apiKeyKey); } + public static class OAuth2RequestInterceptor implements RequestInterceptor { + + private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager; + private final OAuth2AuthorizeRequest oAuth2AuthorizeRequest; + + public OAuth2RequestInterceptor(OAuth2AuthorizeRequest oAuth2AuthorizeRequest,OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager){ + this.oAuth2AuthorizeRequest = oAuth2AuthorizeRequest; + this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager; + } + + @Override + public void apply( final RequestTemplate template ) { + template.header( HttpHeaders.AUTHORIZATION, getBearerToken() ); + } + + public OAuth2AccessToken getAccessToken() { + final OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest); + if (authorizedClient == null) { + throw new OAuth2AuthenticationException( "Client failed to authenticate"); + } + return authorizedClient.getAccessToken(); + } + + public String getBearerToken() { + final OAuth2AccessToken accessToken = getAccessToken(); + return String.format( "%s %s", accessToken.getTokenType().getValue(), accessToken.getTokenValue() ); + } + } + } diff --git a/samples/client/petstore/spring-cloud-feign-without-url/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java b/samples/client/petstore/spring-cloud-feign-without-url/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java new file mode 100644 index 000000000000..bc26dc990a8e --- /dev/null +++ b/samples/client/petstore/spring-cloud-feign-without-url/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java @@ -0,0 +1,10 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.Configuration; + +@PropertySource( "classpath:/oauth2-client.properties" ) +@Configuration +public class ClientPropertiesConfiguration { + +} diff --git a/samples/client/petstore/spring-cloud-feign-without-url/src/main/resources/oauth2-client.properties b/samples/client/petstore/spring-cloud-feign-without-url/src/main/resources/oauth2-client.properties new file mode 100644 index 000000000000..64716bf45f47 --- /dev/null +++ b/samples/client/petstore/spring-cloud-feign-without-url/src/main/resources/oauth2-client.properties @@ -0,0 +1,5 @@ +spring.security.oauth2.client.registration.petstoreAuthImplicit.enabled=false +spring.security.oauth2.client.registration.petstoreAuthImplicit.client-id=set-petstoreAuthImplicit-client-id +spring.security.oauth2.client.registration.petstoreAuthImplicit.scopes=write:pets,read:pets +spring.security.oauth2.client.registration.petstoreAuthImplicit.authorization-grant-type=implicit +spring.security.oauth2.client.provider.petstoreAuthImplicit.authorization-uri=http://petstore.swagger.io/api/oauth/dialog diff --git a/samples/client/petstore/spring-cloud-tags/pom.xml b/samples/client/petstore/spring-cloud-tags/pom.xml index 2d3725b42a13..fd20d7c213d5 100644 --- a/samples/client/petstore/spring-cloud-tags/pom.xml +++ b/samples/client/petstore/spring-cloud-tags/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype diff --git a/samples/client/petstore/spring-cloud/.openapi-generator/FILES b/samples/client/petstore/spring-cloud/.openapi-generator/FILES index 3510d2b2d276..553a884f54d0 100644 --- a/samples/client/petstore/spring-cloud/.openapi-generator/FILES +++ b/samples/client/petstore/spring-cloud/.openapi-generator/FILES @@ -8,9 +8,11 @@ src/main/java/org/openapitools/api/UserApi.java src/main/java/org/openapitools/api/UserApiClient.java src/main/java/org/openapitools/configuration/ApiKeyRequestInterceptor.java src/main/java/org/openapitools/configuration/ClientConfiguration.java +src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java src/main/java/org/openapitools/model/Category.java src/main/java/org/openapitools/model/ModelApiResponse.java src/main/java/org/openapitools/model/Order.java src/main/java/org/openapitools/model/Pet.java src/main/java/org/openapitools/model/Tag.java src/main/java/org/openapitools/model/User.java +src/main/resources/oauth2-client.properties diff --git a/samples/client/petstore/spring-cloud/pom.xml b/samples/client/petstore/spring-cloud/pom.xml index e893d0fa75f0..022cfd58ef9f 100644 --- a/samples/client/petstore/spring-cloud/pom.xml +++ b/samples/client/petstore/spring-cloud/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype diff --git a/samples/client/petstore/spring-cloud/src/main/java/org/openapitools/configuration/ClientConfiguration.java b/samples/client/petstore/spring-cloud/src/main/java/org/openapitools/configuration/ClientConfiguration.java index 49f1c66c11a7..0dc419b64b4f 100644 --- a/samples/client/petstore/spring-cloud/src/main/java/org/openapitools/configuration/ClientConfiguration.java +++ b/samples/client/petstore/spring-cloud/src/main/java/org/openapitools/configuration/ClientConfiguration.java @@ -1,41 +1,45 @@ package org.openapitools.configuration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + import org.springframework.context.annotation.Configuration; -import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; + @Configuration -@EnableConfigurationProperties public class ClientConfiguration { + private static final String CLIENT_PRINCIPAL_IMPLICIT = "oauth2FeignClient"; + @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2FeignRequestInterceptor petstoreAuthRequestInterceptor(OAuth2ClientContext oAuth2ClientContext) { - return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, petstoreAuthResourceDetails()); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2RequestInterceptor implicitOAuth2RequestInterceptor(final OAuth2AuthorizedClientManager implicitAuthorizedClientManager ) { + return new OAuth2RequestInterceptor(OAuth2AuthorizeRequest.withClientRegistrationId("petstoreAuthImplicit") + .principal( new AnonymousAuthenticationToken( CLIENT_PRINCIPAL_IMPLICIT, CLIENT_PRINCIPAL_IMPLICIT, AuthorityUtils.createAuthorityList( "ROLE_ANONYMOUS" ) ) ) + .build(), implicitAuthorizedClientManager ); } @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2ClientContext oAuth2ClientContext() { - return new DefaultOAuth2ClientContext(); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2AuthorizedClientManager implicitAuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService ) { + return new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService ); } - - @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - @ConfigurationProperties("openapipetstore.security.petstoreAuth") - public ImplicitResourceDetails petstoreAuthResourceDetails() { - ImplicitResourceDetails details = new ImplicitResourceDetails(); - details.setUserAuthorizationUri("http://petstore.swagger.io/api/oauth/dialog"); - return details; - } - @Value("${openapipetstore.security.apiKey.key:}") private String apiKeyKey; @@ -45,4 +49,33 @@ public class ClientConfiguration { return new ApiKeyRequestInterceptor("header", "api_key", this.apiKeyKey); } + public static class OAuth2RequestInterceptor implements RequestInterceptor { + + private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager; + private final OAuth2AuthorizeRequest oAuth2AuthorizeRequest; + + public OAuth2RequestInterceptor(OAuth2AuthorizeRequest oAuth2AuthorizeRequest,OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager){ + this.oAuth2AuthorizeRequest = oAuth2AuthorizeRequest; + this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager; + } + + @Override + public void apply( final RequestTemplate template ) { + template.header( HttpHeaders.AUTHORIZATION, getBearerToken() ); + } + + public OAuth2AccessToken getAccessToken() { + final OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest); + if (authorizedClient == null) { + throw new OAuth2AuthenticationException( "Client failed to authenticate"); + } + return authorizedClient.getAccessToken(); + } + + public String getBearerToken() { + final OAuth2AccessToken accessToken = getAccessToken(); + return String.format( "%s %s", accessToken.getTokenType().getValue(), accessToken.getTokenValue() ); + } + } + } diff --git a/samples/client/petstore/spring-cloud/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java b/samples/client/petstore/spring-cloud/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java new file mode 100644 index 000000000000..bc26dc990a8e --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java @@ -0,0 +1,10 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.Configuration; + +@PropertySource( "classpath:/oauth2-client.properties" ) +@Configuration +public class ClientPropertiesConfiguration { + +} diff --git a/samples/client/petstore/spring-cloud/src/main/resources/oauth2-client.properties b/samples/client/petstore/spring-cloud/src/main/resources/oauth2-client.properties new file mode 100644 index 000000000000..64716bf45f47 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/resources/oauth2-client.properties @@ -0,0 +1,5 @@ +spring.security.oauth2.client.registration.petstoreAuthImplicit.enabled=false +spring.security.oauth2.client.registration.petstoreAuthImplicit.client-id=set-petstoreAuthImplicit-client-id +spring.security.oauth2.client.registration.petstoreAuthImplicit.scopes=write:pets,read:pets +spring.security.oauth2.client.registration.petstoreAuthImplicit.authorization-grant-type=implicit +spring.security.oauth2.client.provider.petstoreAuthImplicit.authorization-uri=http://petstore.swagger.io/api/oauth/dialog diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/FILES b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/FILES index 3510d2b2d276..553a884f54d0 100644 --- a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/.openapi-generator/FILES @@ -8,9 +8,11 @@ src/main/java/org/openapitools/api/UserApi.java src/main/java/org/openapitools/api/UserApiClient.java src/main/java/org/openapitools/configuration/ApiKeyRequestInterceptor.java src/main/java/org/openapitools/configuration/ClientConfiguration.java +src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java src/main/java/org/openapitools/model/Category.java src/main/java/org/openapitools/model/ModelApiResponse.java src/main/java/org/openapitools/model/Order.java src/main/java/org/openapitools/model/Pet.java src/main/java/org/openapitools/model/Tag.java src/main/java/org/openapitools/model/User.java +src/main/resources/oauth2-client.properties diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/pom.xml b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/pom.xml index ae5724e75e82..421597d54030 100644 --- a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/pom.xml +++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/pom.xml @@ -54,9 +54,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 6.1.1 com.fasterxml.jackson.datatype diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/configuration/ClientConfiguration.java b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/configuration/ClientConfiguration.java index d938e04a2e83..0dc419b64b4f 100644 --- a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/configuration/ClientConfiguration.java +++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/configuration/ClientConfiguration.java @@ -1,41 +1,45 @@ package org.openapitools.configuration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + import org.springframework.context.annotation.Configuration; -import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; + @Configuration -@EnableConfigurationProperties public class ClientConfiguration { + private static final String CLIENT_PRINCIPAL_IMPLICIT = "oauth2FeignClient"; + @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2FeignRequestInterceptor petstoreAuthRequestInterceptor(OAuth2ClientContext oAuth2ClientContext) { - return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, petstoreAuthResourceDetails()); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2RequestInterceptor implicitOAuth2RequestInterceptor(final OAuth2AuthorizedClientManager implicitAuthorizedClientManager ) { + return new OAuth2RequestInterceptor(OAuth2AuthorizeRequest.withClientRegistrationId("petstoreAuthImplicit") + .principal( new AnonymousAuthenticationToken( CLIENT_PRINCIPAL_IMPLICIT, CLIENT_PRINCIPAL_IMPLICIT, AuthorityUtils.createAuthorityList( "ROLE_ANONYMOUS" ) ) ) + .build(), implicitAuthorizedClientManager ); } @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2ClientContext oAuth2ClientContext() { - return new DefaultOAuth2ClientContext(); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2AuthorizedClientManager implicitAuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService ) { + return new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService ); } - - @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - @ConfigurationProperties("openapipetstore.security.petstoreAuth") - public ImplicitResourceDetails petstoreAuthResourceDetails() { - ImplicitResourceDetails details = new ImplicitResourceDetails(); - details.setUserAuthorizationUri("http://petstore.swagger.io/api/oauth/dialog"); - return details; - } - @Value("${openapipetstore.security.apiKey.key:}") private String apiKeyKey; @@ -45,4 +49,33 @@ public class ClientConfiguration { return new ApiKeyRequestInterceptor("header", "api_key", this.apiKeyKey); } + public static class OAuth2RequestInterceptor implements RequestInterceptor { + + private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager; + private final OAuth2AuthorizeRequest oAuth2AuthorizeRequest; + + public OAuth2RequestInterceptor(OAuth2AuthorizeRequest oAuth2AuthorizeRequest,OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager){ + this.oAuth2AuthorizeRequest = oAuth2AuthorizeRequest; + this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager; + } + + @Override + public void apply( final RequestTemplate template ) { + template.header( HttpHeaders.AUTHORIZATION, getBearerToken() ); + } + + public OAuth2AccessToken getAccessToken() { + final OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest); + if (authorizedClient == null) { + throw new OAuth2AuthenticationException( "Client failed to authenticate"); + } + return authorizedClient.getAccessToken(); + } + + public String getBearerToken() { + final OAuth2AccessToken accessToken = getAccessToken(); + return String.format( "%s %s", accessToken.getTokenType().getValue(), accessToken.getTokenValue() ); + } + } + } diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java new file mode 100644 index 000000000000..bc26dc990a8e --- /dev/null +++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java @@ -0,0 +1,10 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.Configuration; + +@PropertySource( "classpath:/oauth2-client.properties" ) +@Configuration +public class ClientPropertiesConfiguration { + +} diff --git a/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/resources/oauth2-client.properties b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/resources/oauth2-client.properties new file mode 100644 index 000000000000..64716bf45f47 --- /dev/null +++ b/samples/openapi3/client/petstore/spring-cloud-3-with-optional/src/main/resources/oauth2-client.properties @@ -0,0 +1,5 @@ +spring.security.oauth2.client.registration.petstoreAuthImplicit.enabled=false +spring.security.oauth2.client.registration.petstoreAuthImplicit.client-id=set-petstoreAuthImplicit-client-id +spring.security.oauth2.client.registration.petstoreAuthImplicit.scopes=write:pets,read:pets +spring.security.oauth2.client.registration.petstoreAuthImplicit.authorization-grant-type=implicit +spring.security.oauth2.client.provider.petstoreAuthImplicit.authorization-uri=http://petstore.swagger.io/api/oauth/dialog diff --git a/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/FILES b/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/FILES index 3510d2b2d276..553a884f54d0 100644 --- a/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/spring-cloud-3/.openapi-generator/FILES @@ -8,9 +8,11 @@ src/main/java/org/openapitools/api/UserApi.java src/main/java/org/openapitools/api/UserApiClient.java src/main/java/org/openapitools/configuration/ApiKeyRequestInterceptor.java src/main/java/org/openapitools/configuration/ClientConfiguration.java +src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java src/main/java/org/openapitools/model/Category.java src/main/java/org/openapitools/model/ModelApiResponse.java src/main/java/org/openapitools/model/Order.java src/main/java/org/openapitools/model/Pet.java src/main/java/org/openapitools/model/Tag.java src/main/java/org/openapitools/model/User.java +src/main/resources/oauth2-client.properties diff --git a/samples/openapi3/client/petstore/spring-cloud-3/pom.xml b/samples/openapi3/client/petstore/spring-cloud-3/pom.xml index b38ba97282c9..a68d685f4b8a 100644 --- a/samples/openapi3/client/petstore/spring-cloud-3/pom.xml +++ b/samples/openapi3/client/petstore/spring-cloud-3/pom.xml @@ -61,9 +61,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 6.1.1 com.fasterxml.jackson.datatype diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/configuration/ClientConfiguration.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/configuration/ClientConfiguration.java index d938e04a2e83..0dc419b64b4f 100644 --- a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/configuration/ClientConfiguration.java +++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/configuration/ClientConfiguration.java @@ -1,41 +1,45 @@ package org.openapitools.configuration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + import org.springframework.context.annotation.Configuration; -import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; + @Configuration -@EnableConfigurationProperties public class ClientConfiguration { + private static final String CLIENT_PRINCIPAL_IMPLICIT = "oauth2FeignClient"; + @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2FeignRequestInterceptor petstoreAuthRequestInterceptor(OAuth2ClientContext oAuth2ClientContext) { - return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, petstoreAuthResourceDetails()); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2RequestInterceptor implicitOAuth2RequestInterceptor(final OAuth2AuthorizedClientManager implicitAuthorizedClientManager ) { + return new OAuth2RequestInterceptor(OAuth2AuthorizeRequest.withClientRegistrationId("petstoreAuthImplicit") + .principal( new AnonymousAuthenticationToken( CLIENT_PRINCIPAL_IMPLICIT, CLIENT_PRINCIPAL_IMPLICIT, AuthorityUtils.createAuthorityList( "ROLE_ANONYMOUS" ) ) ) + .build(), implicitAuthorizedClientManager ); } @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2ClientContext oAuth2ClientContext() { - return new DefaultOAuth2ClientContext(); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2AuthorizedClientManager implicitAuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService ) { + return new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService ); } - - @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - @ConfigurationProperties("openapipetstore.security.petstoreAuth") - public ImplicitResourceDetails petstoreAuthResourceDetails() { - ImplicitResourceDetails details = new ImplicitResourceDetails(); - details.setUserAuthorizationUri("http://petstore.swagger.io/api/oauth/dialog"); - return details; - } - @Value("${openapipetstore.security.apiKey.key:}") private String apiKeyKey; @@ -45,4 +49,33 @@ public class ClientConfiguration { return new ApiKeyRequestInterceptor("header", "api_key", this.apiKeyKey); } + public static class OAuth2RequestInterceptor implements RequestInterceptor { + + private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager; + private final OAuth2AuthorizeRequest oAuth2AuthorizeRequest; + + public OAuth2RequestInterceptor(OAuth2AuthorizeRequest oAuth2AuthorizeRequest,OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager){ + this.oAuth2AuthorizeRequest = oAuth2AuthorizeRequest; + this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager; + } + + @Override + public void apply( final RequestTemplate template ) { + template.header( HttpHeaders.AUTHORIZATION, getBearerToken() ); + } + + public OAuth2AccessToken getAccessToken() { + final OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest); + if (authorizedClient == null) { + throw new OAuth2AuthenticationException( "Client failed to authenticate"); + } + return authorizedClient.getAccessToken(); + } + + public String getBearerToken() { + final OAuth2AccessToken accessToken = getAccessToken(); + return String.format( "%s %s", accessToken.getTokenType().getValue(), accessToken.getTokenValue() ); + } + } + } diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java new file mode 100644 index 000000000000..bc26dc990a8e --- /dev/null +++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java @@ -0,0 +1,10 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.Configuration; + +@PropertySource( "classpath:/oauth2-client.properties" ) +@Configuration +public class ClientPropertiesConfiguration { + +} diff --git a/samples/openapi3/client/petstore/spring-cloud-3/src/main/resources/oauth2-client.properties b/samples/openapi3/client/petstore/spring-cloud-3/src/main/resources/oauth2-client.properties new file mode 100644 index 000000000000..64716bf45f47 --- /dev/null +++ b/samples/openapi3/client/petstore/spring-cloud-3/src/main/resources/oauth2-client.properties @@ -0,0 +1,5 @@ +spring.security.oauth2.client.registration.petstoreAuthImplicit.enabled=false +spring.security.oauth2.client.registration.petstoreAuthImplicit.client-id=set-petstoreAuthImplicit-client-id +spring.security.oauth2.client.registration.petstoreAuthImplicit.scopes=write:pets,read:pets +spring.security.oauth2.client.registration.petstoreAuthImplicit.authorization-grant-type=implicit +spring.security.oauth2.client.provider.petstoreAuthImplicit.authorization-uri=http://petstore.swagger.io/api/oauth/dialog diff --git a/samples/openapi3/client/petstore/spring-cloud-async/.openapi-generator/FILES b/samples/openapi3/client/petstore/spring-cloud-async/.openapi-generator/FILES index 3510d2b2d276..553a884f54d0 100644 --- a/samples/openapi3/client/petstore/spring-cloud-async/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/spring-cloud-async/.openapi-generator/FILES @@ -8,9 +8,11 @@ src/main/java/org/openapitools/api/UserApi.java src/main/java/org/openapitools/api/UserApiClient.java src/main/java/org/openapitools/configuration/ApiKeyRequestInterceptor.java src/main/java/org/openapitools/configuration/ClientConfiguration.java +src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java src/main/java/org/openapitools/model/Category.java src/main/java/org/openapitools/model/ModelApiResponse.java src/main/java/org/openapitools/model/Order.java src/main/java/org/openapitools/model/Pet.java src/main/java/org/openapitools/model/Tag.java src/main/java/org/openapitools/model/User.java +src/main/resources/oauth2-client.properties diff --git a/samples/openapi3/client/petstore/spring-cloud-async/pom.xml b/samples/openapi3/client/petstore/spring-cloud-async/pom.xml index f92a06b51ead..908ac33927dd 100644 --- a/samples/openapi3/client/petstore/spring-cloud-async/pom.xml +++ b/samples/openapi3/client/petstore/spring-cloud-async/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype diff --git a/samples/openapi3/client/petstore/spring-cloud-async/src/main/java/org/openapitools/configuration/ClientConfiguration.java b/samples/openapi3/client/petstore/spring-cloud-async/src/main/java/org/openapitools/configuration/ClientConfiguration.java index 49f1c66c11a7..0dc419b64b4f 100644 --- a/samples/openapi3/client/petstore/spring-cloud-async/src/main/java/org/openapitools/configuration/ClientConfiguration.java +++ b/samples/openapi3/client/petstore/spring-cloud-async/src/main/java/org/openapitools/configuration/ClientConfiguration.java @@ -1,41 +1,45 @@ package org.openapitools.configuration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + import org.springframework.context.annotation.Configuration; -import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; + @Configuration -@EnableConfigurationProperties public class ClientConfiguration { + private static final String CLIENT_PRINCIPAL_IMPLICIT = "oauth2FeignClient"; + @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2FeignRequestInterceptor petstoreAuthRequestInterceptor(OAuth2ClientContext oAuth2ClientContext) { - return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, petstoreAuthResourceDetails()); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2RequestInterceptor implicitOAuth2RequestInterceptor(final OAuth2AuthorizedClientManager implicitAuthorizedClientManager ) { + return new OAuth2RequestInterceptor(OAuth2AuthorizeRequest.withClientRegistrationId("petstoreAuthImplicit") + .principal( new AnonymousAuthenticationToken( CLIENT_PRINCIPAL_IMPLICIT, CLIENT_PRINCIPAL_IMPLICIT, AuthorityUtils.createAuthorityList( "ROLE_ANONYMOUS" ) ) ) + .build(), implicitAuthorizedClientManager ); } @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2ClientContext oAuth2ClientContext() { - return new DefaultOAuth2ClientContext(); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2AuthorizedClientManager implicitAuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService ) { + return new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService ); } - - @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - @ConfigurationProperties("openapipetstore.security.petstoreAuth") - public ImplicitResourceDetails petstoreAuthResourceDetails() { - ImplicitResourceDetails details = new ImplicitResourceDetails(); - details.setUserAuthorizationUri("http://petstore.swagger.io/api/oauth/dialog"); - return details; - } - @Value("${openapipetstore.security.apiKey.key:}") private String apiKeyKey; @@ -45,4 +49,33 @@ public class ClientConfiguration { return new ApiKeyRequestInterceptor("header", "api_key", this.apiKeyKey); } + public static class OAuth2RequestInterceptor implements RequestInterceptor { + + private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager; + private final OAuth2AuthorizeRequest oAuth2AuthorizeRequest; + + public OAuth2RequestInterceptor(OAuth2AuthorizeRequest oAuth2AuthorizeRequest,OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager){ + this.oAuth2AuthorizeRequest = oAuth2AuthorizeRequest; + this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager; + } + + @Override + public void apply( final RequestTemplate template ) { + template.header( HttpHeaders.AUTHORIZATION, getBearerToken() ); + } + + public OAuth2AccessToken getAccessToken() { + final OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest); + if (authorizedClient == null) { + throw new OAuth2AuthenticationException( "Client failed to authenticate"); + } + return authorizedClient.getAccessToken(); + } + + public String getBearerToken() { + final OAuth2AccessToken accessToken = getAccessToken(); + return String.format( "%s %s", accessToken.getTokenType().getValue(), accessToken.getTokenValue() ); + } + } + } diff --git a/samples/openapi3/client/petstore/spring-cloud-async/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java b/samples/openapi3/client/petstore/spring-cloud-async/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java new file mode 100644 index 000000000000..bc26dc990a8e --- /dev/null +++ b/samples/openapi3/client/petstore/spring-cloud-async/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java @@ -0,0 +1,10 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.Configuration; + +@PropertySource( "classpath:/oauth2-client.properties" ) +@Configuration +public class ClientPropertiesConfiguration { + +} diff --git a/samples/openapi3/client/petstore/spring-cloud-async/src/main/resources/oauth2-client.properties b/samples/openapi3/client/petstore/spring-cloud-async/src/main/resources/oauth2-client.properties new file mode 100644 index 000000000000..64716bf45f47 --- /dev/null +++ b/samples/openapi3/client/petstore/spring-cloud-async/src/main/resources/oauth2-client.properties @@ -0,0 +1,5 @@ +spring.security.oauth2.client.registration.petstoreAuthImplicit.enabled=false +spring.security.oauth2.client.registration.petstoreAuthImplicit.client-id=set-petstoreAuthImplicit-client-id +spring.security.oauth2.client.registration.petstoreAuthImplicit.scopes=write:pets,read:pets +spring.security.oauth2.client.registration.petstoreAuthImplicit.authorization-grant-type=implicit +spring.security.oauth2.client.provider.petstoreAuthImplicit.authorization-uri=http://petstore.swagger.io/api/oauth/dialog diff --git a/samples/openapi3/client/petstore/spring-cloud-date-time/pom.xml b/samples/openapi3/client/petstore/spring-cloud-date-time/pom.xml index 9deb1212be26..c169a34fd7c6 100644 --- a/samples/openapi3/client/petstore/spring-cloud-date-time/pom.xml +++ b/samples/openapi3/client/petstore/spring-cloud-date-time/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype diff --git a/samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/pom.xml b/samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/pom.xml index 3d15a0a25657..db3b788efc80 100644 --- a/samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/pom.xml +++ b/samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype diff --git a/samples/openapi3/client/petstore/spring-cloud-spring-pageable/.openapi-generator/FILES b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/.openapi-generator/FILES index 3510d2b2d276..553a884f54d0 100644 --- a/samples/openapi3/client/petstore/spring-cloud-spring-pageable/.openapi-generator/FILES +++ b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/.openapi-generator/FILES @@ -8,9 +8,11 @@ src/main/java/org/openapitools/api/UserApi.java src/main/java/org/openapitools/api/UserApiClient.java src/main/java/org/openapitools/configuration/ApiKeyRequestInterceptor.java src/main/java/org/openapitools/configuration/ClientConfiguration.java +src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java src/main/java/org/openapitools/model/Category.java src/main/java/org/openapitools/model/ModelApiResponse.java src/main/java/org/openapitools/model/Order.java src/main/java/org/openapitools/model/Pet.java src/main/java/org/openapitools/model/Tag.java src/main/java/org/openapitools/model/User.java +src/main/resources/oauth2-client.properties diff --git a/samples/openapi3/client/petstore/spring-cloud-spring-pageable/pom.xml b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/pom.xml index 67b135e6143e..5d2158943488 100644 --- a/samples/openapi3/client/petstore/spring-cloud-spring-pageable/pom.xml +++ b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype diff --git a/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/configuration/ClientConfiguration.java b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/configuration/ClientConfiguration.java index 49f1c66c11a7..0dc419b64b4f 100644 --- a/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/configuration/ClientConfiguration.java +++ b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/configuration/ClientConfiguration.java @@ -1,41 +1,45 @@ package org.openapitools.configuration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AnonymousAuthenticationToken; +import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import feign.RequestInterceptor; +import feign.RequestTemplate; + import org.springframework.context.annotation.Configuration; -import org.springframework.cloud.openfeign.security.OAuth2FeignRequestInterceptor; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; + @Configuration -@EnableConfigurationProperties public class ClientConfiguration { + private static final String CLIENT_PRINCIPAL_IMPLICIT = "oauth2FeignClient"; + @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2FeignRequestInterceptor petstoreAuthRequestInterceptor(OAuth2ClientContext oAuth2ClientContext) { - return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, petstoreAuthResourceDetails()); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2RequestInterceptor implicitOAuth2RequestInterceptor(final OAuth2AuthorizedClientManager implicitAuthorizedClientManager ) { + return new OAuth2RequestInterceptor(OAuth2AuthorizeRequest.withClientRegistrationId("petstoreAuthImplicit") + .principal( new AnonymousAuthenticationToken( CLIENT_PRINCIPAL_IMPLICIT, CLIENT_PRINCIPAL_IMPLICIT, AuthorityUtils.createAuthorityList( "ROLE_ANONYMOUS" ) ) ) + .build(), implicitAuthorizedClientManager ); } @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - public OAuth2ClientContext oAuth2ClientContext() { - return new DefaultOAuth2ClientContext(); + @ConditionalOnProperty( prefix = "spring.security.oauth2.client.registration.petstoreAuthImplicit", name = "enabled", havingValue = "true" ) + public OAuth2AuthorizedClientManager implicitAuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService ) { + return new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService ); } - - @Bean - @ConditionalOnProperty("openapipetstore.security.petstoreAuth.client-id") - @ConfigurationProperties("openapipetstore.security.petstoreAuth") - public ImplicitResourceDetails petstoreAuthResourceDetails() { - ImplicitResourceDetails details = new ImplicitResourceDetails(); - details.setUserAuthorizationUri("http://petstore.swagger.io/api/oauth/dialog"); - return details; - } - @Value("${openapipetstore.security.apiKey.key:}") private String apiKeyKey; @@ -45,4 +49,33 @@ public class ClientConfiguration { return new ApiKeyRequestInterceptor("header", "api_key", this.apiKeyKey); } + public static class OAuth2RequestInterceptor implements RequestInterceptor { + + private final OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager; + private final OAuth2AuthorizeRequest oAuth2AuthorizeRequest; + + public OAuth2RequestInterceptor(OAuth2AuthorizeRequest oAuth2AuthorizeRequest,OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager){ + this.oAuth2AuthorizeRequest = oAuth2AuthorizeRequest; + this.oAuth2AuthorizedClientManager = oAuth2AuthorizedClientManager; + } + + @Override + public void apply( final RequestTemplate template ) { + template.header( HttpHeaders.AUTHORIZATION, getBearerToken() ); + } + + public OAuth2AccessToken getAccessToken() { + final OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest); + if (authorizedClient == null) { + throw new OAuth2AuthenticationException( "Client failed to authenticate"); + } + return authorizedClient.getAccessToken(); + } + + public String getBearerToken() { + final OAuth2AccessToken accessToken = getAccessToken(); + return String.format( "%s %s", accessToken.getTokenType().getValue(), accessToken.getTokenValue() ); + } + } + } diff --git a/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java new file mode 100644 index 000000000000..bc26dc990a8e --- /dev/null +++ b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/java/org/openapitools/configuration/ClientPropertiesConfiguration.java @@ -0,0 +1,10 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.Configuration; + +@PropertySource( "classpath:/oauth2-client.properties" ) +@Configuration +public class ClientPropertiesConfiguration { + +} diff --git a/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/resources/oauth2-client.properties b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/resources/oauth2-client.properties new file mode 100644 index 000000000000..64716bf45f47 --- /dev/null +++ b/samples/openapi3/client/petstore/spring-cloud-spring-pageable/src/main/resources/oauth2-client.properties @@ -0,0 +1,5 @@ +spring.security.oauth2.client.registration.petstoreAuthImplicit.enabled=false +spring.security.oauth2.client.registration.petstoreAuthImplicit.client-id=set-petstoreAuthImplicit-client-id +spring.security.oauth2.client.registration.petstoreAuthImplicit.scopes=write:pets,read:pets +spring.security.oauth2.client.registration.petstoreAuthImplicit.authorization-grant-type=implicit +spring.security.oauth2.client.provider.petstoreAuthImplicit.authorization-uri=http://petstore.swagger.io/api/oauth/dialog diff --git a/samples/openapi3/client/petstore/spring-cloud/pom.xml b/samples/openapi3/client/petstore/spring-cloud/pom.xml index 3d15a0a25657..db3b788efc80 100644 --- a/samples/openapi3/client/petstore/spring-cloud/pom.xml +++ b/samples/openapi3/client/petstore/spring-cloud/pom.xml @@ -52,9 +52,9 @@ spring-cloud-starter-openfeign - org.springframework.cloud - spring-cloud-starter-oauth2 - 2.2.5.RELEASE + org.springframework.security + spring-security-oauth2-client + 5.7.8 com.fasterxml.jackson.datatype