Skip to content

Commit dc9ff73

Browse files
eddumelendezwilkinsona
authored andcommitted
Enable customization of RestTemplate that retrieves JwtAccessTokenConverter's key
Closes gh-8268 See gh-5859
1 parent 1d9520b commit dc9ff73

File tree

3 files changed

+83
-4
lines changed

3 files changed

+83
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2012-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.security.oauth2.resource;
18+
19+
import org.springframework.web.client.RestTemplate;
20+
21+
/**
22+
* Callback for customizing the rest template used to fetch the token key.
23+
*
24+
* @author Eddú Meléndez
25+
* @since 1.5.2
26+
*/
27+
public interface JwtAccessTokenConverterRestTemplateCustomizer {
28+
29+
/**
30+
* Customize the rest template before it is initialized.
31+
* @param template the rest template
32+
*/
33+
void customize(RestTemplate template);
34+
35+
}

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
*
7777
* @author Dave Syer
7878
* @author Madhura Bhave
79+
* @author Eddú Meléndez
7980
* @since 1.3.0
8081
*/
8182
@Configuration
@@ -245,16 +246,18 @@ public TokenStore jwkTokenStore() {
245246
@Conditional(JwtTokenCondition.class)
246247
protected static class JwtTokenServicesConfiguration {
247248

248-
private RestTemplate keyUriRestTemplate = new RestTemplate();
249-
250249
private final ResourceServerProperties resource;
251250

252251
private final List<JwtAccessTokenConverterConfigurer> configurers;
253252

253+
private final List<JwtAccessTokenConverterRestTemplateCustomizer> customizers;
254+
254255
public JwtTokenServicesConfiguration(ResourceServerProperties resource,
255-
ObjectProvider<List<JwtAccessTokenConverterConfigurer>> configurers) {
256+
ObjectProvider<List<JwtAccessTokenConverterConfigurer>> configurers,
257+
ObjectProvider<List<JwtAccessTokenConverterRestTemplateCustomizer>> customizers) {
256258
this.resource = resource;
257259
this.configurers = configurers.getIfAvailable();
260+
this.customizers = customizers.getIfAvailable();
258261
}
259262

260263
@Bean
@@ -299,6 +302,10 @@ public JwtAccessTokenConverter jwtTokenEnhancer() {
299302
}
300303

301304
private String getKeyFromServer() {
305+
RestTemplate keyUriRestTemplate = new RestTemplate();
306+
for (JwtAccessTokenConverterRestTemplateCustomizer customizer : this.customizers) {
307+
customizer.customize(keyUriRestTemplate);
308+
}
302309
HttpHeaders headers = new HttpHeaders();
303310
String username = this.resource.getClientId();
304311
String password = this.resource.getClientSecret();
@@ -308,7 +315,7 @@ private String getKeyFromServer() {
308315
}
309316
HttpEntity<Void> request = new HttpEntity<Void>(headers);
310317
String url = this.resource.getJwt().getKeyUri();
311-
return (String) this.keyUriRestTemplate
318+
return (String) keyUriRestTemplate
312319
.exchange(url, HttpMethod.GET, request, Map.class).getBody()
313320
.get("value");
314321
}

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfigurationTests.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
5757
import org.springframework.social.connect.ConnectionFactoryLocator;
5858
import org.springframework.stereotype.Component;
59+
import org.springframework.web.client.RestTemplate;
5960

6061
import static org.assertj.core.api.Assertions.assertThat;
6162
import static org.mockito.Mockito.mock;
@@ -65,6 +66,7 @@
6566
*
6667
* @author Dave Syer
6768
* @author Madhura Bhave
69+
* @author Eddú Meléndez
6870
*/
6971
public class ResourceServerTokenServicesConfigurationTests {
7072

@@ -240,6 +242,23 @@ public void customUserInfoRestTemplateFactory() {
240242
.isInstanceOf(CustomUserInfoRestTemplateFactory.class);
241243
}
242244

245+
@Test
246+
public void customRestTemplate() {
247+
EnvironmentTestUtils.addEnvironment(this.environment,
248+
"security.oauth2.resource.userInfoUri:http://example.com",
249+
"security.oauth2.resource.tokenInfoUri:http://example.com",
250+
"security.oauth2.resource.preferTokenInfo:false");
251+
this.context = new SpringApplicationBuilder(ResourceConfiguration.class,
252+
RestTemplateCustomizer.class).environment(this.environment).web(false)
253+
.run();
254+
String[] restTemplateCustomizers = this.context
255+
.getBeanNamesForType(JwtAccessTokenConverterRestTemplateCustomizer.class);
256+
UserInfoTokenServices services = this.context
257+
.getBean(UserInfoTokenServices.class);
258+
assertThat(restTemplateCustomizers).hasSize(1);
259+
assertThat(services).isNotNull();
260+
}
261+
243262
@Configuration
244263
@Import({ ResourceServerTokenServicesConfiguration.class,
245264
ResourceServerPropertiesConfiguration.class,
@@ -354,4 +373,22 @@ public OAuth2RestTemplate getUserInfoRestTemplate() {
354373

355374
}
356375

376+
@Component
377+
protected static class RestTemplateCustomizer
378+
implements JwtAccessTokenConverterRestTemplateCustomizer {
379+
380+
@Override
381+
public void customize(RestTemplate template) {
382+
template.getInterceptors().add(new ClientHttpRequestInterceptor() {
383+
384+
@Override
385+
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
386+
ClientHttpRequestExecution execution) throws IOException {
387+
return execution.execute(request, body);
388+
}
389+
390+
});
391+
}
392+
}
393+
357394
}

0 commit comments

Comments
 (0)