From 00f9adafd7bcd23191251ebf6ca50f69ef166077 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 13 May 2016 17:26:22 +0200 Subject: [PATCH] Stop creating a primary `Oauth2RestTemplate` This commit removes the creation of a `@Primary` `OAuth2RestTemplate` and updates the documentation accordingly. Once #5507 is implemented we could revisit this area to provide a way for users to easily create such a bean. Closes gh-5202 --- .../OAuth2RestOperationsConfiguration.java | 12 --- ...plateBasicOAuth2SsoConfigurationTests.java | 86 +++++++++++++++++++ .../main/asciidoc/spring-boot-features.adoc | 34 ++++++-- 3 files changed, 111 insertions(+), 21 deletions(-) create mode 100644 spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/sso/CustomRestTemplateBasicOAuth2SsoConfigurationTests.java diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2RestOperationsConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2RestOperationsConfiguration.java index d3f92cfa95..463f8370d7 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2RestOperationsConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2RestOperationsConfiguration.java @@ -43,10 +43,7 @@ import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2ClientContext; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; -import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.token.AccessTokenRequest; import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; @@ -69,15 +66,6 @@ import org.springframework.util.StringUtils; @Conditional(OAuth2ClientIdCondition.class) public class OAuth2RestOperationsConfiguration { - @Bean - @Primary - public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext, - OAuth2ProtectedResourceDetails details) { - OAuth2RestTemplate template = new OAuth2RestTemplate(details, - oauth2ClientContext); - return template; - } - @Configuration @ConditionalOnNotWebApplication protected static class SingletonScopedConfiguration { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/sso/CustomRestTemplateBasicOAuth2SsoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/sso/CustomRestTemplateBasicOAuth2SsoConfigurationTests.java new file mode 100644 index 0000000000..2815b272bc --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/sso/CustomRestTemplateBasicOAuth2SsoConfigurationTests.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012-2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.security.oauth2.sso; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration; +import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Primary; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.client.RestTemplate; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Test to validate that a custom {@link RestTemplate} can be defined + * with OAuth2 SSO. + * + * @author Stephane Nicoll + */ +@RunWith(SpringRunner.class) +@DirtiesContext +@SpringBootTest +@TestPropertySource(properties = {"security.oauth2.client.clientId=client", + "security.oauth2.client.clientSecret=secret", + "security.oauth2.client.userAuthorizationUri=http://example.com/oauth/authorize", + "security.oauth2.client.accessTokenUri=http://example.com/oauth/token", + "security.oauth2.resource.jwt.keyValue=SSSSHHH"}) +public class CustomRestTemplateBasicOAuth2SsoConfigurationTests { + + @Autowired + private ApplicationContext applicationContext; + + @Autowired + private ObjectProvider restTemplateProvider; + + @Test + public void customRestTemplateCanBePrimary() { + RestTemplate restTemplate = this.restTemplateProvider.getIfAvailable(); + verifyZeroInteractions(restTemplate); + assertThat(this.applicationContext.getBeansOfType(RestTemplate.class)).hasSize(2); + } + + @Configuration + @Import(OAuth2AutoConfiguration.class) + @EnableOAuth2Sso + @MinimalSecureWebConfiguration + protected static class TestConfiguration { + + @Bean + @Primary + public RestTemplate myRestTemplate() { + return mock(RestTemplate.class); + } + + } + +} + + diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 9fde94d6ae..5cfba037a4 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -2296,11 +2296,27 @@ language feature). Example: [[boot-features-security-custom-user-info-client]] ==== Client -To make your webapp into an OAuth2 client you can simply add `@EnableOAuth2Client` and -Spring Boot will create an `OAuth2RestTemplate` for you to `@Autowire`. It uses the -`security.oauth2.client.*` as credentials (the same as you might be using in the -Authorization Server), but in addition it will need to know the authorization and token -URIs in the Authorization Server. For example: +To make your web-app into an OAuth2 client you can simply add `@EnableOAuth2Client` and +Spring Boot will create a `OAuth2ClientContext` and `OAuth2ProtectedResourceDetails` that +are necessary to create an `OAuth2RestOperations`. Spring Boot does not automatically +create such bean but you can easily create your own: + +[source,java,indent=0] +---- + + @Bean + public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext, + OAuth2ProtectedResourceDetails details) { + return new OAuth2RestTemplate(details, oauth2ClientContext); + } +---- + +NOTE: You may want to add a qualifier and review your configuration as more than one +`RestTemplate` may be defined in your application. + +This configuration uses `security.oauth2.client.*` as credentials (the same as you might +be using in the Authorization Server), but in addition it will need to know the +authorization and token URIs in the Authorization Server. For example: .application.yml [source,yaml,indent=0] @@ -2332,12 +2348,12 @@ instance, your OAuth2 provider doesn't like header authentication). In fact, the `security.oauth2.client.*` properties are bound to an instance of `AuthorizationCodeResourceDetails` so all its properties can be specified. -TIP: In a non-web application you can still `@Autowire` an `OAuth2RestOperations` and it +TIP: In a non-web application you can still create an `OAuth2RestOperations` and it is still wired into the `security.oauth2.client.*` configuration. In this case it is a "`client credentials token grant`" you will be asking for if you use it (and there is no -need to use `@EnableOAuth2Client` or `@EnableOAuth2Sso`). To switch it off, just remove -the `security.oauth2.client.client-id` from your configuration (or make it the empty -string). +need to use `@EnableOAuth2Client` or `@EnableOAuth2Sso`). To prevent that infrastructure +to be defined, just remove the `security.oauth2.client.client-id` from your configuration +(or make it the empty string).