Skip to content

Commit 72db6a2

Browse files
committed
Don't Cache ReactiveJwtDecoders Errors
Closes gh-10444
1 parent 00f4033 commit 72db6a2

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolver.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.security.oauth2.server.resource.authentication;
1818

19+
import java.time.Duration;
1920
import java.util.ArrayList;
2021
import java.util.Arrays;
2122
import java.util.Collection;
@@ -186,7 +187,7 @@ public Mono<ReactiveAuthenticationManager> resolve(String issuer) {
186187
return this.authenticationManagers.computeIfAbsent(issuer,
187188
(k) -> Mono.<ReactiveAuthenticationManager>fromCallable(() -> new JwtReactiveAuthenticationManager(ReactiveJwtDecoders.fromIssuerLocation(k)))
188189
.subscribeOn(Schedulers.boundedElastic())
189-
.cache()
190+
.cache((manager) -> Duration.ofMillis(Long.MAX_VALUE), (ex) -> Duration.ZERO, () -> Duration.ZERO)
190191
);
191192
// @formatter:on
192193
}

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerAuthenticationManagerResolverTests.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,44 @@ public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() thro
9696
}
9797
}
9898

99+
@Test
100+
public void resolveWhednUsingTrustedIssuerThenReturnsAuthenticationManager() throws Exception {
101+
try (MockWebServer server = new MockWebServer()) {
102+
server.start();
103+
String issuer = server.url("").toString();
104+
// @formatter:off
105+
server.enqueue(new MockResponse().setResponseCode(500)
106+
.setHeader("Content-Type", "application/json")
107+
.setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer))
108+
);
109+
server.enqueue(new MockResponse().setResponseCode(200)
110+
.setHeader("Content-Type", "application/json")
111+
.setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer))
112+
);
113+
server.enqueue(new MockResponse().setResponseCode(200)
114+
.setHeader("Content-Type", "application/json")
115+
.setBody(JWK_SET)
116+
);
117+
server.enqueue(new MockResponse().setResponseCode(200)
118+
.setHeader("Content-Type", "application/json")
119+
.setBody(JWK_SET)
120+
);
121+
// @formatter:on
122+
JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256),
123+
new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer))));
124+
jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY));
125+
JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver(
126+
issuer);
127+
Authentication token = withBearerToken(jws.serialize());
128+
AuthenticationManager authenticationManager = authenticationManagerResolver.resolve(null);
129+
assertThat(authenticationManager).isNotNull();
130+
assertThatExceptionOfType(IllegalArgumentException.class)
131+
.isThrownBy(() -> authenticationManager.authenticate(token));
132+
Authentication authentication = authenticationManager.authenticate(token);
133+
assertThat(authentication.isAuthenticated()).isTrue();
134+
}
135+
}
136+
99137
@Test
100138
public void resolveWhenUsingSameIssuerThenReturnsSameAuthenticationManager() throws Exception {
101139
try (MockWebServer server = new MockWebServer()) {

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtIssuerReactiveAuthenticationManagerResolverTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,36 @@ public void resolveWhenUsingTrustedIssuerThenReturnsAuthenticationManager() thro
9595
}
9696
}
9797

98+
// gh-10444
99+
@Test
100+
public void resolveWhednUsingTrustedIssuerThenReturnsAuthenticationManager() throws Exception {
101+
try (MockWebServer server = new MockWebServer()) {
102+
String issuer = server.url("").toString();
103+
// @formatter:off
104+
server.enqueue(new MockResponse().setResponseCode(500).setHeader("Content-Type", "application/json")
105+
.setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer)));
106+
server.enqueue(new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json")
107+
.setBody(String.format(DEFAULT_RESPONSE_TEMPLATE, issuer, issuer)));
108+
server.enqueue(new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json")
109+
.setBody(JWK_SET));
110+
server.enqueue(new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json")
111+
.setBody(JWK_SET));
112+
// @formatter:on
113+
JWSObject jws = new JWSObject(new JWSHeader(JWSAlgorithm.RS256),
114+
new Payload(new JSONObject(Collections.singletonMap(JwtClaimNames.ISS, issuer))));
115+
jws.sign(new RSASSASigner(TestKeys.DEFAULT_PRIVATE_KEY));
116+
JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerReactiveAuthenticationManagerResolver(
117+
issuer);
118+
ReactiveAuthenticationManager authenticationManager = authenticationManagerResolver.resolve(null).block();
119+
assertThat(authenticationManager).isNotNull();
120+
Authentication token = withBearerToken(jws.serialize());
121+
assertThatExceptionOfType(IllegalArgumentException.class)
122+
.isThrownBy(() -> authenticationManager.authenticate(token).block());
123+
Authentication authentication = authenticationManager.authenticate(token).block();
124+
assertThat(authentication.isAuthenticated()).isTrue();
125+
}
126+
}
127+
98128
@Test
99129
public void resolveWhenUsingSameIssuerThenReturnsSameAuthenticationManager() throws Exception {
100130
try (MockWebServer server = new MockWebServer()) {

0 commit comments

Comments
 (0)