Skip to content

Commit d8ae8b3

Browse files
committed
Improve brittle tests using opaque token introspection
The tests that went through opaque token introspection rely on mocking a specific method in the RestOperations interface which is very brittle and hampers the ability to refactor internals. They are changed to instead make actual HTTP requests to a MockWebServer instead allowing refactoring changes. This is necessary to allow the implementation to be swapped from NimbusOpaqueTokenIntrospector to SpringOpaqueTokenIntrospector because the latter uses RestOperations#exchange(String, ParameterizedType) instead of RestOperations#exchange(String, String) of the former. Signed-off-by: Andreas Svanberg <[email protected]>
1 parent 270df71 commit d8ae8b3

File tree

2 files changed

+16
-17
lines changed

2 files changed

+16
-17
lines changed

config/src/test/java/org/springframework/security/config/http/OAuth2ResourceServerBeanDefinitionParserTests.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
import org.springframework.util.LinkedMultiValueMap;
100100
import org.springframework.util.MultiValueMap;
101101
import org.springframework.web.client.RestOperations;
102+
import org.springframework.web.client.RestTemplate;
102103

103104
import static org.assertj.core.api.Assertions.assertThat;
104105
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -659,8 +660,8 @@ public void requestWhenUsingPublicKeyAlgorithmDoesNotMatchThenReturnsInvalidToke
659660

660661
@Test
661662
public void getWhenIntrospectingThenOk() throws Exception {
662-
this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire();
663-
mockRestOperations(json("Active"));
663+
this.spring.configLocations(xml("OpaqueTokenWebServer"), xml("OpaqueToken")).autowire();
664+
mockWebServer(json("Active"));
664665
// @formatter:off
665666
this.mvc.perform(get("/authenticated").header("Authorization", "Bearer token"))
666667
.andExpect(status().isNotFound());
@@ -669,9 +670,9 @@ public void getWhenIntrospectingThenOk() throws Exception {
669670

670671
@Test
671672
public void configureWhenIntrospectingWithAuthenticationConverterThenUses() throws Exception {
672-
this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueTokenAndAuthenticationConverter"))
673+
this.spring.configLocations(xml("OpaqueTokenWebServer"), xml("OpaqueTokenAndAuthenticationConverter"))
673674
.autowire();
674-
mockRestOperations(json("Active"));
675+
mockWebServer(json("Active"));
675676
OpaqueTokenAuthenticationConverter converter = bean(OpaqueTokenAuthenticationConverter.class);
676677
given(converter.convert(any(), any())).willReturn(new TestingAuthenticationToken("user", "pass", "app"));
677678
// @formatter:off
@@ -683,8 +684,8 @@ public void configureWhenIntrospectingWithAuthenticationConverterThenUses() thro
683684

684685
@Test
685686
public void getWhenIntrospectionFailsThenUnauthorized() throws Exception {
686-
this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire();
687-
mockRestOperations(json("Inactive"));
687+
this.spring.configLocations(xml("OpaqueTokenWebServer"), xml("OpaqueToken")).autowire();
688+
mockWebServer(json("Inactive"));
688689
// @formatter:off
689690
MockHttpServletRequestBuilder request = get("/")
690691
.header("Authorization", "Bearer token");
@@ -696,8 +697,8 @@ public void getWhenIntrospectionFailsThenUnauthorized() throws Exception {
696697

697698
@Test
698699
public void getWhenIntrospectionLacksScopeThenForbidden() throws Exception {
699-
this.spring.configLocations(xml("OpaqueTokenRestOperations"), xml("OpaqueToken")).autowire();
700-
mockRestOperations(json("ActiveNoScopes"));
700+
this.spring.configLocations(xml("OpaqueTokenWebServer"), xml("OpaqueToken")).autowire();
701+
mockWebServer(json("ActiveNoScopes"));
701702
// @formatter:off
702703
this.mvc.perform(get("/requires-read-scope").header("Authorization", "Bearer token"))
703704
.andExpect(status().isForbidden())
@@ -1028,20 +1029,20 @@ public void setRest(RestOperations rest) {
10281029

10291030
static class OpaqueTokenIntrospectorFactoryBean implements FactoryBean<OpaqueTokenIntrospector> {
10301031

1031-
private RestOperations rest;
1032+
private String introspectionUri;
10321033

10331034
@Override
10341035
public OpaqueTokenIntrospector getObject() throws Exception {
1035-
return new NimbusOpaqueTokenIntrospector("https://idp.example.org", this.rest);
1036+
return new NimbusOpaqueTokenIntrospector(this.introspectionUri, new RestTemplate());
10361037
}
10371038

10381039
@Override
10391040
public Class<?> getObjectType() {
10401041
return OpaqueTokenIntrospector.class;
10411042
}
10421043

1043-
public void setRest(RestOperations rest) {
1044-
this.rest = rest;
1044+
public void setIntrospectionUri(String introspectionUri) {
1045+
this.introspectionUri = introspectionUri;
10451046
}
10461047

10471048
}
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,10 @@
2121
xsi:schemaLocation="http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
2222
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
2323

24-
<b:bean name="rest" class="org.mockito.Mockito" factory-method="mock">
25-
<b:constructor-arg value="org.springframework.web.client.RestOperations" type="java.lang.Class"/>
26-
</b:bean>
27-
2824
<b:bean name="introspector"
2925
class="org.springframework.security.config.http.OAuth2ResourceServerBeanDefinitionParserTests$OpaqueTokenIntrospectorFactoryBean">
30-
<b:property name="rest" ref="rest"/>
26+
<b:property name="introspectionUri" value="${introspection-uri}"/>
3127
</b:bean>
28+
29+
<b:import resource="OAuth2ResourceServerBeanDefinitionParserTests-WebServer.xml"/>
3230
</b:beans>

0 commit comments

Comments
 (0)