|
|
|
|
@ -19,7 +19,6 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.se
@@ -19,7 +19,6 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.se
|
|
|
|
|
import java.io.BufferedReader; |
|
|
|
|
import java.io.FileReader; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.lang.reflect.Field; |
|
|
|
|
import java.security.KeyFactory; |
|
|
|
|
import java.security.interfaces.RSAPublicKey; |
|
|
|
|
import java.security.spec.X509EncodedKeySpec; |
|
|
|
|
@ -34,6 +33,8 @@ import java.util.Map;
@@ -34,6 +33,8 @@ import java.util.Map;
|
|
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
import javax.annotation.PreDestroy; |
|
|
|
|
|
|
|
|
|
import com.nimbusds.jose.proc.SecurityContext; |
|
|
|
|
import com.nimbusds.jwt.proc.JWTProcessor; |
|
|
|
|
import okhttp3.mockwebserver.MockResponse; |
|
|
|
|
import okhttp3.mockwebserver.MockWebServer; |
|
|
|
|
import org.hamcrest.core.AllOf; |
|
|
|
|
@ -43,20 +44,25 @@ import org.hamcrest.core.StringStartsWith;
@@ -43,20 +44,25 @@ import org.hamcrest.core.StringStartsWith;
|
|
|
|
|
import org.junit.Rule; |
|
|
|
|
import org.junit.Test; |
|
|
|
|
|
|
|
|
|
import org.springframework.beans.BeansException; |
|
|
|
|
import org.springframework.beans.factory.BeanCreationException; |
|
|
|
|
import org.springframework.beans.factory.NoUniqueBeanDefinitionException; |
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
|
import org.springframework.beans.factory.config.BeanPostProcessor; |
|
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
|
import org.springframework.context.EnvironmentAware; |
|
|
|
|
import org.springframework.context.annotation.Bean; |
|
|
|
|
import org.springframework.context.annotation.Configuration; |
|
|
|
|
import org.springframework.core.convert.converter.Converter; |
|
|
|
|
import org.springframework.core.env.ConfigurableEnvironment; |
|
|
|
|
import org.springframework.core.env.Environment; |
|
|
|
|
import org.springframework.core.env.PropertySource; |
|
|
|
|
import org.springframework.core.io.ClassPathResource; |
|
|
|
|
import org.springframework.data.util.ReflectionUtils; |
|
|
|
|
import org.springframework.http.HttpHeaders; |
|
|
|
|
import org.springframework.http.HttpStatus; |
|
|
|
|
import org.springframework.http.MediaType; |
|
|
|
|
import org.springframework.http.RequestEntity; |
|
|
|
|
import org.springframework.http.ResponseEntity; |
|
|
|
|
import org.springframework.mock.web.MockHttpServletRequest; |
|
|
|
|
import org.springframework.security.access.prepost.PreAuthorize; |
|
|
|
|
import org.springframework.security.authentication.AbstractAuthenticationToken; |
|
|
|
|
@ -79,6 +85,7 @@ import org.springframework.security.oauth2.jwt.Jwt;
@@ -79,6 +85,7 @@ import org.springframework.security.oauth2.jwt.Jwt;
|
|
|
|
|
import org.springframework.security.oauth2.jwt.JwtClaimNames; |
|
|
|
|
import org.springframework.security.oauth2.jwt.JwtDecoder; |
|
|
|
|
import org.springframework.security.oauth2.jwt.JwtException; |
|
|
|
|
import org.springframework.security.oauth2.jwt.JwtProcessors; |
|
|
|
|
import org.springframework.security.oauth2.jwt.JwtTimestampValidator; |
|
|
|
|
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; |
|
|
|
|
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; |
|
|
|
|
@ -102,6 +109,7 @@ import org.springframework.web.bind.annotation.GetMapping;
@@ -102,6 +109,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|
|
|
|
import org.springframework.web.bind.annotation.PostMapping; |
|
|
|
|
import org.springframework.web.bind.annotation.RequestMapping; |
|
|
|
|
import org.springframework.web.bind.annotation.RestController; |
|
|
|
|
import org.springframework.web.client.RestOperations; |
|
|
|
|
import org.springframework.web.context.support.GenericWebApplicationContext; |
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
|
@ -110,10 +118,10 @@ import static org.hamcrest.CoreMatchers.containsString;
@@ -110,10 +118,10 @@ import static org.hamcrest.CoreMatchers.containsString;
|
|
|
|
|
import static org.hamcrest.core.StringStartsWith.startsWith; |
|
|
|
|
import static org.mockito.ArgumentMatchers.any; |
|
|
|
|
import static org.mockito.ArgumentMatchers.anyString; |
|
|
|
|
import static org.mockito.ArgumentMatchers.eq; |
|
|
|
|
import static org.mockito.Mockito.mock; |
|
|
|
|
import static org.mockito.Mockito.verify; |
|
|
|
|
import static org.mockito.Mockito.when; |
|
|
|
|
import static org.springframework.security.oauth2.jwt.JwtProcessors.withJwkSetUri; |
|
|
|
|
import static org.springframework.security.oauth2.jwt.JwtProcessors.withPublicKey; |
|
|
|
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; |
|
|
|
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; |
|
|
|
|
@ -145,7 +153,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -145,7 +153,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
MockMvc mvc; |
|
|
|
|
|
|
|
|
|
@Autowired(required = false) |
|
|
|
|
MockWebServer authz; |
|
|
|
|
MockWebServer web; |
|
|
|
|
|
|
|
|
|
@Rule |
|
|
|
|
public final SpringTestRule spring = new SpringTestRule(); |
|
|
|
|
@ -154,8 +162,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -154,8 +162,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithValidBearerTokenThenAcceptsRequest() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken(token))) |
|
|
|
|
@ -163,12 +171,24 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -163,12 +171,24 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
.andExpect(content().string("ok")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getWhenUsingJwkSetUriThenAcceptsRequest() throws Exception { |
|
|
|
|
this.spring.register(WebServerConfig.class, JwkSetUriConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockWebServer(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken(token))) |
|
|
|
|
.andExpect(status().isOk()) |
|
|
|
|
.andExpect(content().string("ok")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void getWhenUsingDefaultsWithExpiredBearerTokenThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("Expired"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken(token))) |
|
|
|
|
@ -180,8 +200,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -180,8 +200,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithBadJwkEndpointThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
this.authz.enqueue(new MockResponse().setBody("malformed")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
mockRestOperations("malformed"); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken(token))) |
|
|
|
|
@ -193,8 +213,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -193,8 +213,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithUnavailableJwkEndpointThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
this.authz.shutdown(); |
|
|
|
|
this.spring.register(WebServerConfig.class, JwkSetUriConfig.class).autowire(); |
|
|
|
|
this.web.shutdown(); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken(token))) |
|
|
|
|
@ -206,7 +226,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -206,7 +226,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithMalformedBearerTokenThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(DefaultConfig.class).autowire(); |
|
|
|
|
this.spring.register(JwkSetUriConfig.class).autowire(); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken("an\"invalid\"token"))) |
|
|
|
|
.andExpect(status().isUnauthorized()) |
|
|
|
|
@ -217,8 +237,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -217,8 +237,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithMalformedPayloadThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("MalformedPayload"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken(token))) |
|
|
|
|
@ -230,7 +250,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -230,7 +250,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithUnsignedBearerTokenThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(DefaultConfig.class).autowire(); |
|
|
|
|
this.spring.register(JwkSetUriConfig.class).autowire(); |
|
|
|
|
String token = this.token("Unsigned"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken(token))) |
|
|
|
|
@ -242,8 +262,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -242,8 +262,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithBearerTokenBeforeNotBeforeThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
this.mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("TooEarly"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/").with(bearerToken(token))) |
|
|
|
|
@ -255,7 +275,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -255,7 +275,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithBearerTokenInTwoPlacesThenInvalidRequest() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(DefaultConfig.class).autowire(); |
|
|
|
|
this.spring.register(JwkSetUriConfig.class).autowire(); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/") |
|
|
|
|
.with(bearerToken("token")) |
|
|
|
|
@ -268,7 +288,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -268,7 +288,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithBearerTokenInTwoParametersThenInvalidRequest() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(DefaultConfig.class).autowire(); |
|
|
|
|
this.spring.register(JwkSetUriConfig.class).autowire(); |
|
|
|
|
|
|
|
|
|
MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); |
|
|
|
|
params.add("access_token", "token1"); |
|
|
|
|
@ -284,7 +304,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -284,7 +304,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void postWhenUsingDefaultsWithBearerTokenAsFormParameterThenIgnoresToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(DefaultConfig.class).autowire(); |
|
|
|
|
this.spring.register(JwkSetUriConfig.class).autowire(); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(post("/") // engage csrf
|
|
|
|
|
.with(bearerToken("token").asParam())) |
|
|
|
|
@ -308,7 +328,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -308,7 +328,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithNoBearerTokenThenUnauthorized() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(DefaultConfig.class).autowire(); |
|
|
|
|
this.spring.register(JwkSetUriConfig.class).autowire(); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/")) |
|
|
|
|
.andExpect(status().isUnauthorized()) |
|
|
|
|
@ -319,8 +339,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -319,8 +339,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithSufficientlyScopedBearerTokenThenAcceptsRequest() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidMessageReadScope"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/requires-read-scope") |
|
|
|
|
@ -333,8 +353,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -333,8 +353,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithInsufficientScopeThenInsufficientScopeError() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/requires-read-scope") |
|
|
|
|
@ -347,8 +367,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -347,8 +367,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsWithInsufficientScpThenInsufficientScopeError() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidMessageWriteScp"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/requires-read-scope") |
|
|
|
|
@ -361,8 +381,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -361,8 +381,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsAndAuthorizationServerHasNoMatchingKeyThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Empty")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Empty")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/") |
|
|
|
|
@ -375,8 +395,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -375,8 +395,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsAndAuthorizationServerHasMultipleMatchingKeysThenOk() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("TwoKeys")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("TwoKeys")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/authenticated") |
|
|
|
|
@ -389,8 +409,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -389,8 +409,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingDefaultsAndKeyMatchesByKidThenOk() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("TwoKeys")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("TwoKeys")); |
|
|
|
|
String token = this.token("Kid"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/authenticated") |
|
|
|
|
@ -405,8 +425,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -405,8 +425,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingMethodSecurityWithValidBearerTokenThenAcceptsRequest() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidMessageReadScope"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/ms-requires-read-scope") |
|
|
|
|
@ -419,8 +439,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -419,8 +439,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingMethodSecurityWithValidBearerTokenHavingScpAttributeThenAcceptsRequest() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidMessageReadScp"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/ms-requires-read-scope") |
|
|
|
|
@ -433,8 +453,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -433,8 +453,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingMethodSecurityWithInsufficientScopeThenInsufficientScopeError() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/ms-requires-read-scope") |
|
|
|
|
@ -448,8 +468,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -448,8 +468,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingMethodSecurityWithInsufficientScpThenInsufficientScopeError() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidMessageWriteScp"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/ms-requires-read-scope") |
|
|
|
|
@ -462,8 +482,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -462,8 +482,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenUsingMethodSecurityWithDenyAllThenInsufficientScopeError() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, MethodSecurityConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidMessageReadScope"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/ms-deny") |
|
|
|
|
@ -478,8 +498,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -478,8 +498,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void postWhenUsingDefaultsWithValidBearerTokenAndNoCsrfTokenThenOk() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(post("/authenticated") |
|
|
|
|
@ -492,7 +512,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -492,7 +512,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void postWhenUsingDefaultsWithNoBearerTokenThenCsrfDenies() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(DefaultConfig.class).autowire(); |
|
|
|
|
this.spring.register(JwkSetUriConfig.class).autowire(); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(post("/authenticated")) |
|
|
|
|
.andExpect(status().isForbidden()) |
|
|
|
|
@ -503,8 +523,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -503,8 +523,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void postWhenUsingDefaultsWithExpiredBearerTokenAndNoCsrfThenInvalidToken() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("Expired"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(post("/authenticated") |
|
|
|
|
@ -519,8 +539,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -519,8 +539,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void requestWhenDefaultConfiguredThenSessionIsNotCreated() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
MvcResult result = this.mvc.perform(get("/") |
|
|
|
|
@ -535,7 +555,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -535,7 +555,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void requestWhenUsingDefaultsAndNoBearerTokenThenSessionIsCreated() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(DefaultConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.spring.register(JwkSetUriConfig.class, BasicController.class).autowire(); |
|
|
|
|
|
|
|
|
|
MvcResult result = this.mvc.perform(get("/")) |
|
|
|
|
.andExpect(status().isUnauthorized()) |
|
|
|
|
@ -548,8 +568,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -548,8 +568,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void requestWhenSessionManagementConfiguredThenUserConfigurationOverrides() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, AlwaysSessionCreationConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, AlwaysSessionCreationConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
MvcResult result = this.mvc.perform(get("/") |
|
|
|
|
@ -868,8 +888,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -868,8 +888,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void requestWhenCustomJwtValidatorFailsThenCorrespondingErrorMessage() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, CustomJwtValidatorConfig.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, CustomJwtValidatorConfig.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
OAuth2TokenValidator<Jwt> jwtValidator = |
|
|
|
|
@ -890,8 +910,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -890,8 +910,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void requestWhenClockSkewSetThenTimestampWindowRelaxedAccordingly() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, UnexpiredJwtClockSkewConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, UnexpiredJwtClockSkewConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ExpiresAt4687177990"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/") |
|
|
|
|
@ -903,8 +923,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -903,8 +923,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void requestWhenClockSkewSetButJwtStillTooLateThenReportsExpired() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, ExpiredJwtClockSkewConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, ExpiredJwtClockSkewConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ExpiresAt4687177990"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/") |
|
|
|
|
@ -1067,8 +1087,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1067,8 +1087,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
public void getWhenAlsoUsingHttpBasicThenCorrectProviderEngages() |
|
|
|
|
throws Exception { |
|
|
|
|
|
|
|
|
|
this.spring.register(WebServerConfig.class, BasicAndResourceServerConfig.class, BasicController.class).autowire(); |
|
|
|
|
this.authz.enqueue(this.jwks("Default")); |
|
|
|
|
this.spring.register(RestOperationsConfig.class, BasicAndResourceServerConfig.class, BasicController.class).autowire(); |
|
|
|
|
mockRestOperations(jwks("Default")); |
|
|
|
|
String token = this.token("ValidNoScopes"); |
|
|
|
|
|
|
|
|
|
this.mvc.perform(get("/authenticated") |
|
|
|
|
@ -1104,7 +1124,25 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1104,7 +1124,25 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
static class DefaultConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mock.jwk-set-uri:https://example.org}") String uri; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
// @formatter:off
|
|
|
|
|
http |
|
|
|
|
.authorizeRequests() |
|
|
|
|
.antMatchers("/requires-read-scope").access("hasAuthority('SCOPE_message:read')") |
|
|
|
|
.anyRequest().authenticated() |
|
|
|
|
.and() |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt(); |
|
|
|
|
// @formatter:on
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
static class JwkSetUriConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mockwebserver.url:https://example.org}") |
|
|
|
|
String jwkSetUri; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
@ -1116,14 +1154,15 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1116,14 +1154,15 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
.and() |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt() |
|
|
|
|
.jwkSetUri(this.uri); |
|
|
|
|
.jwkSetUri(this.jwkSetUri); |
|
|
|
|
// @formatter:on
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
static class CsrfDisabledConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mock.jwk-set-uri:https://example.org}") String uri; |
|
|
|
|
@Value("${mockwebserver.url:https://example.org}") |
|
|
|
|
String jwkSetUri; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
@ -1136,7 +1175,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1136,7 +1175,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
.csrf().disable() |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt() |
|
|
|
|
.jwkSetUri(this.uri); |
|
|
|
|
.jwkSetUri(this.jwkSetUri); |
|
|
|
|
// @formatter:on
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -1144,8 +1183,6 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1144,8 +1183,6 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
@EnableGlobalMethodSecurity(prePostEnabled = true) |
|
|
|
|
static class MethodSecurityConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mock.jwk-set-uri:https://example.org}") String uri; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
// @formatter:off
|
|
|
|
|
@ -1154,8 +1191,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1154,8 +1191,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
.anyRequest().authenticated() |
|
|
|
|
.and() |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt() |
|
|
|
|
.jwkSetUri(this.uri); |
|
|
|
|
.jwt(); |
|
|
|
|
// @formatter:on
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -1303,8 +1339,6 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1303,8 +1339,6 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
static class BasicAndResourceServerConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mock.jwk-set-uri:https://example.org}") String uri; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
// @formatter:off
|
|
|
|
|
@ -1315,8 +1349,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1315,8 +1349,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
.httpBasic() |
|
|
|
|
.and() |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt() |
|
|
|
|
.jwkSetUri(this.uri); |
|
|
|
|
.jwt(); |
|
|
|
|
// @formatter:on
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1365,8 +1398,6 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1365,8 +1398,6 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
static class AlwaysSessionCreationConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mock.jwk-set-uri}") String uri; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
// @formatter:off
|
|
|
|
|
@ -1375,8 +1406,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1375,8 +1406,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS) |
|
|
|
|
.and() |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt() |
|
|
|
|
.jwkSetUri(this.uri); |
|
|
|
|
.jwt(); |
|
|
|
|
// @formatter:on
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -1498,20 +1528,19 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1498,20 +1528,19 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
static class CustomJwtValidatorConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mock.jwk-set-uri}") String uri; |
|
|
|
|
@Autowired |
|
|
|
|
NimbusJwtDecoder jwtDecoder; |
|
|
|
|
|
|
|
|
|
private final OAuth2TokenValidator<Jwt> jwtValidator = mock(OAuth2TokenValidator.class); |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder(withJwkSetUri(this.uri).build()); |
|
|
|
|
jwtDecoder.setJwtValidator(this.jwtValidator); |
|
|
|
|
this.jwtDecoder.setJwtValidator(this.jwtValidator); |
|
|
|
|
|
|
|
|
|
// @formatter:off
|
|
|
|
|
http |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt() |
|
|
|
|
.decoder(jwtDecoder); |
|
|
|
|
.jwt(); |
|
|
|
|
// @formatter:on
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1522,7 +1551,8 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1522,7 +1551,8 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
static class UnexpiredJwtClockSkewConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mock.jwk-set-uri}") String uri; |
|
|
|
|
@Autowired |
|
|
|
|
NimbusJwtDecoder jwtDecoder; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
@ -1531,21 +1561,20 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1531,21 +1561,20 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
JwtTimestampValidator jwtValidator = new JwtTimestampValidator(Duration.ofHours(1)); |
|
|
|
|
jwtValidator.setClock(nearlyAnHourFromTokenExpiry); |
|
|
|
|
|
|
|
|
|
NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder(withJwkSetUri(this.uri).build()); |
|
|
|
|
jwtDecoder.setJwtValidator(jwtValidator); |
|
|
|
|
this.jwtDecoder.setJwtValidator(jwtValidator); |
|
|
|
|
|
|
|
|
|
// @formatter:off
|
|
|
|
|
http |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt() |
|
|
|
|
.decoder(jwtDecoder); |
|
|
|
|
.jwt(); |
|
|
|
|
// @formatter:on
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@EnableWebSecurity |
|
|
|
|
static class ExpiredJwtClockSkewConfig extends WebSecurityConfigurerAdapter { |
|
|
|
|
@Value("${mock.jwk-set-uri}") String uri; |
|
|
|
|
@Autowired |
|
|
|
|
NimbusJwtDecoder jwtDecoder; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void configure(HttpSecurity http) throws Exception { |
|
|
|
|
@ -1554,14 +1583,12 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1554,14 +1583,12 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
JwtTimestampValidator jwtValidator = new JwtTimestampValidator(Duration.ofHours(1)); |
|
|
|
|
jwtValidator.setClock(justOverOneHourAfterExpiry); |
|
|
|
|
|
|
|
|
|
NimbusJwtDecoder jwtDecoder = new NimbusJwtDecoder(withJwkSetUri(this.uri).build()); |
|
|
|
|
jwtDecoder.setJwtValidator(jwtValidator); |
|
|
|
|
this.jwtDecoder.setJwtValidator(jwtValidator); |
|
|
|
|
|
|
|
|
|
// @formatter:off
|
|
|
|
|
http |
|
|
|
|
.oauth2ResourceServer() |
|
|
|
|
.jwt() |
|
|
|
|
.decoder(jwtDecoder); |
|
|
|
|
.jwt(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1643,7 +1670,7 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1643,7 +1670,7 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
static class WebServerConfig implements BeanPostProcessor { |
|
|
|
|
static class WebServerConfig implements BeanPostProcessor, EnvironmentAware { |
|
|
|
|
private final MockWebServer server = new MockWebServer(); |
|
|
|
|
|
|
|
|
|
@PreDestroy |
|
|
|
|
@ -1651,21 +1678,51 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1651,21 +1678,51 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
this.server.shutdown(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void setEnvironment(Environment environment) { |
|
|
|
|
if (environment instanceof ConfigurableEnvironment) { |
|
|
|
|
((ConfigurableEnvironment) environment) |
|
|
|
|
.getPropertySources().addFirst(new MockWebServerPropertySource()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
public MockWebServer authz() { |
|
|
|
|
public MockWebServer web() { |
|
|
|
|
return this.server; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { |
|
|
|
|
if (bean instanceof WebSecurityConfigurerAdapter) { |
|
|
|
|
Field f = ReflectionUtils.findField(bean.getClass(), field -> |
|
|
|
|
field.getAnnotation(Value.class) != null); |
|
|
|
|
if (f != null) { |
|
|
|
|
ReflectionUtils.setField(f, bean, this.server.url("/.well-known/jwks.json").toString()); |
|
|
|
|
private class MockWebServerPropertySource extends PropertySource { |
|
|
|
|
|
|
|
|
|
public MockWebServerPropertySource() { |
|
|
|
|
super("mockwebserver"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Object getProperty(String name) { |
|
|
|
|
if ("mockwebserver.url".equals(name)) { |
|
|
|
|
return WebServerConfig.this.server.url("/.well-known/jwks.json").toString(); |
|
|
|
|
} else { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
|
static class RestOperationsConfig { |
|
|
|
|
RestOperations rest = mock(RestOperations.class); |
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
RestOperations rest() { |
|
|
|
|
return this.rest; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Bean |
|
|
|
|
NimbusJwtDecoder jwtDecoder() { |
|
|
|
|
JWTProcessor<SecurityContext> jwtProcessor = |
|
|
|
|
JwtProcessors.withJwkSetUri("https://example.org/.well-known/jwks.json") |
|
|
|
|
.restOperations(this.rest).build(); |
|
|
|
|
return new NimbusJwtDecoder(jwtProcessor); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1733,16 +1790,25 @@ public class OAuth2ResourceServerConfigurerTests {
@@ -1733,16 +1790,25 @@ public class OAuth2ResourceServerConfigurerTests {
|
|
|
|
|
(StringUtils.hasText(scope) ? ", scope=\"" + scope + "\"" : "")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String token(String name) throws IOException { |
|
|
|
|
return resource(name + ".token"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private MockResponse jwks(String name) throws IOException { |
|
|
|
|
String response = resource(name + ".jwks"); |
|
|
|
|
return new MockResponse() |
|
|
|
|
private void mockWebServer(String response) { |
|
|
|
|
this.web.enqueue(new MockResponse() |
|
|
|
|
.setResponseCode(200) |
|
|
|
|
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) |
|
|
|
|
.setBody(response); |
|
|
|
|
.setBody(response)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void mockRestOperations(String response) { |
|
|
|
|
RestOperations rest = this.spring.getContext().getBean(RestOperations.class); |
|
|
|
|
when(rest.exchange(any(RequestEntity.class), eq(String.class))) |
|
|
|
|
.thenReturn(new ResponseEntity<>(response, HttpStatus.OK)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String jwks(String name) throws IOException { |
|
|
|
|
return resource(name + ".jwks"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String token(String name) throws IOException { |
|
|
|
|
return resource(name + ".token"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private String resource(String suffix) throws IOException { |
|
|
|
|
|