From f5f65463d2f5da3c39c00dc1b5799807fd3b4e39 Mon Sep 17 00:00:00 2001 From: Walter Seymore Date: Tue, 18 Apr 2017 15:17:15 +0100 Subject: [PATCH] Fail fast on getKeyFromServer() failure Update `ResourceServerTokenServicesConfiguration` to fail fast if the `getKeyFromServer()` call fails. Since the key is part of the singleton `JwtAccessTokenConverter` bean there is not real way to refresh without restarting the application. A hard failure seems preferable to an inconsistent state. Closes gh-8924 --- ...ourceServerTokenServicesConfiguration.java | 15 +------ ...ServerTokenServicesConfigurationTests.java | 42 ++++++++++++------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration.java index 7e1504ad82..16ce76ca01 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration.java @@ -21,9 +21,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionMessage; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; @@ -68,7 +65,6 @@ import org.springframework.social.connect.support.OAuth2ConnectionFactory; import org.springframework.util.CollectionUtils; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; /** @@ -83,9 +79,6 @@ import org.springframework.web.client.RestTemplate; @ConditionalOnMissingBean(AuthorizationServerEndpointsConfiguration.class) public class ResourceServerTokenServicesConfiguration { - private static final Log logger = LogFactory - .getLog(ResourceServerTokenServicesConfiguration.class); - @Bean @ConditionalOnMissingBean public UserInfoRestTemplateFactory userInfoRestTemplateFactory( @@ -278,13 +271,7 @@ public class ResourceServerTokenServicesConfiguration { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); String keyValue = this.resource.getJwt().getKeyValue(); if (!StringUtils.hasText(keyValue)) { - try { - keyValue = getKeyFromServer(); - } - catch (ResourceAccessException ex) { - logger.warn("Failed to fetch token key (you may need to refresh " - + "when the auth server is back)"); - } + keyValue = getKeyFromServer(); } if (StringUtils.hasText(keyValue) && !keyValue.startsWith("-----BEGIN")) { converter.setSigningKey(keyValue); diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfigurationTests.java index e41923711e..04630ab628 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfigurationTests.java @@ -45,9 +45,12 @@ import org.springframework.context.annotation.Import; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.StandardEnvironment; import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; +import org.springframework.mock.http.client.MockClientHttpResponse; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.client.OAuth2RestTemplate; @@ -60,9 +63,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; /** * Tests for {@link ResourceServerTokenServicesConfiguration}. @@ -247,23 +248,12 @@ public class ResourceServerTokenServicesConfigurationTests { @Test public void jwtAccessTokenConverterIsConfiguredWhenKeyUriIsProvided() { - EnvironmentTestUtils.addEnvironment(this.environment, - "security.oauth2.resource.jwt.key-uri=http://localhost:12345/banana"); - this.context = new SpringApplicationBuilder(ResourceConfiguration.class) - .environment(this.environment).web(false).run(); - assertThat(this.context.getBeansOfType(JwtAccessTokenConverter.class)).hasSize(1); - } - - @Test - public void jwtAccessTokenConverterRestTemplateCanBeCustomized() { EnvironmentTestUtils.addEnvironment(this.environment, "security.oauth2.resource.jwt.key-uri=http://localhost:12345/banana"); this.context = new SpringApplicationBuilder(ResourceConfiguration.class, JwtAccessTokenConverterRestTemplateCustomizerConfiguration.class) .environment(this.environment).web(false).run(); - JwtAccessTokenConverterRestTemplateCustomizer customizer = this.context - .getBean(JwtAccessTokenConverterRestTemplateCustomizer.class); - verify(customizer).customize(any(RestTemplate.class)); + assertThat(this.context.getBeansOfType(JwtAccessTokenConverter.class)).hasSize(1); } @Configuration @@ -385,7 +375,29 @@ public class ResourceServerTokenServicesConfigurationTests { @Bean public JwtAccessTokenConverterRestTemplateCustomizer restTemplateCustomizer() { - return mock(JwtAccessTokenConverterRestTemplateCustomizer.class); + return new MockRestCallCustomizer(); + } + + } + + private static class MockRestCallCustomizer + implements JwtAccessTokenConverterRestTemplateCustomizer { + + @Override + public void customize(RestTemplate template) { + template.getInterceptors().add(new ClientHttpRequestInterceptor() { + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution) throws IOException { + String payload = "{\"value\":\"FOO\"}"; + MockClientHttpResponse response = new MockClientHttpResponse( + payload.getBytes(), HttpStatus.OK); + response.getHeaders().setContentType(MediaType.APPLICATION_JSON); + return response; + } + + }); } }