diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java index addbf73fc9..2769b7e4e0 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java @@ -81,6 +81,12 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { private MockWebServer server; + private static final String JWK_SET = "{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"use\":\"sig\"," + + "\"kid\":\"one\",\"n\":\"oXJ8OyOv_eRnce4akdanR4KYRfnC2zLV4uYNQpcFn6oHL0dj7D6kxQmsXoYgJV8ZVDn71KGm" + + "uLvolxsDncc2UrhyMBY6DVQVgMSVYaPCTgW76iYEKGgzTEw5IBRQL9w3SRJWd3VJTZZQjkXef48Ocz06PGF3lhbz4t5UEZtd" + + "F4rIe7u-977QwHuh7yRPBQ3sII-cVoOUMgaXB9SHcGF2iZCtPzL_IffDUcfhLQteGebhW8A6eUHgpD5A1PQ-JCw_G7UOzZAj" + + "jDjtNM2eqm8j-Ms_gqnm4MiCZ4E-9pDN77CAAPVN7kuX6ejs9KBXpk01z48i9fORYk9u7rAkh1HuQw\"}]}"; + @AfterEach void cleanup() throws Exception { if (this.server != null) { @@ -137,7 +143,8 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { assertFilterConfiguredWithJwtAuthenticationManager(context); assertThat(context.containsBean("jwtDecoderByIssuerUri")).isTrue(); }); - assertThat(this.server.getRequestCount()).isEqualTo(1); + // The last request is to the JWK Set endpoint to look up the algorithm + assertThat(this.server.getRequestCount()).isEqualTo(2); } @Test @@ -153,7 +160,8 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { assertFilterConfiguredWithJwtAuthenticationManager(context); assertThat(context.containsBean("jwtDecoderByIssuerUri")).isTrue(); }); - assertThat(this.server.getRequestCount()).isEqualTo(2); + // The last request is to the JWK Set endpoint to look up the algorithm + assertThat(this.server.getRequestCount()).isEqualTo(3); } @Test @@ -169,7 +177,8 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { assertFilterConfiguredWithJwtAuthenticationManager(context); assertThat(context.containsBean("jwtDecoderByIssuerUri")).isTrue(); }); - assertThat(this.server.getRequestCount()).isEqualTo(3); + // The last request is to the JWK Set endpoint to look up the algorithm + assertThat(this.server.getRequestCount()).isEqualTo(4); } @Test @@ -396,6 +405,8 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { .setBody(new ObjectMapper().writeValueAsString(getResponse(issuer))) .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); this.server.enqueue(mockResponse); + this.server.enqueue( + new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json").setBody(JWK_SET)); } private void setupMockResponsesWithErrors(String issuer, int errorResponseCount) throws JsonProcessingException { @@ -413,7 +424,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { response.put("code_challenge_methods_supported", Collections.emptyList()); response.put("id_token_signing_alg_values_supported", Collections.emptyList()); response.put("issuer", issuer); - response.put("jwks_uri", "https://example.com/oauth2/v3/certs"); + response.put("jwks_uri", issuer + "/.well-known/jwks.json"); response.put("response_types_supported", Collections.emptyList()); response.put("revocation_endpoint", "https://example.com/o/oauth2/revoke"); response.put("scopes_supported", Collections.singletonList("openid")); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerAutoConfigurationTests.java index 91b207cc17..dc4f7cc214 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/servlet/OAuth2ResourceServerAutoConfigurationTests.java @@ -75,6 +75,12 @@ class OAuth2ResourceServerAutoConfigurationTests { private MockWebServer server; + private static final String JWK_SET = "{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"use\":\"sig\"," + + "\"kid\":\"one\",\"n\":\"oXJ8OyOv_eRnce4akdanR4KYRfnC2zLV4uYNQpcFn6oHL0dj7D6kxQmsXoYgJV8ZVDn71KGm" + + "uLvolxsDncc2UrhyMBY6DVQVgMSVYaPCTgW76iYEKGgzTEw5IBRQL9w3SRJWd3VJTZZQjkXef48Ocz06PGF3lhbz4t5UEZtd" + + "F4rIe7u-977QwHuh7yRPBQ3sII-cVoOUMgaXB9SHcGF2iZCtPzL_IffDUcfhLQteGebhW8A6eUHgpD5A1PQ-JCw_G7UOzZAj" + + "jDjtNM2eqm8j-Ms_gqnm4MiCZ4E-9pDN77CAAPVN7kuX6ejs9KBXpk01z48i9fORYk9u7rAkh1HuQw\"}]}"; + @AfterEach void cleanup() throws Exception { if (this.server != null) { @@ -133,7 +139,8 @@ class OAuth2ResourceServerAutoConfigurationTests { assertThat(context).hasSingleBean(JwtDecoder.class); assertThat(context.containsBean("jwtDecoderByIssuerUri")).isTrue(); }); - assertThat(this.server.getRequestCount()).isEqualTo(1); + // The last request is to the JWK Set endpoint to look up the algorithm + assertThat(this.server.getRequestCount()).isEqualTo(2); } @Test @@ -149,7 +156,8 @@ class OAuth2ResourceServerAutoConfigurationTests { assertThat(context).hasSingleBean(JwtDecoder.class); assertThat(context.containsBean("jwtDecoderByIssuerUri")).isTrue(); }); - assertThat(this.server.getRequestCount()).isEqualTo(2); + // The last request is to the JWK Set endpoint to look up the algorithm + assertThat(this.server.getRequestCount()).isEqualTo(3); } @Test @@ -165,7 +173,8 @@ class OAuth2ResourceServerAutoConfigurationTests { assertThat(context).hasSingleBean(JwtDecoder.class); assertThat(context.containsBean("jwtDecoderByIssuerUri")).isTrue(); }); - assertThat(this.server.getRequestCount()).isEqualTo(3); + // The last request is to the JWK Set endpoint to look up the algorithm + assertThat(this.server.getRequestCount()).isEqualTo(4); } @Test @@ -414,6 +423,8 @@ class OAuth2ResourceServerAutoConfigurationTests { .setBody(new ObjectMapper().writeValueAsString(getResponse(issuer))) .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); this.server.enqueue(mockResponse); + this.server.enqueue( + new MockResponse().setResponseCode(200).setHeader("Content-Type", "application/json").setBody(JWK_SET)); } private void setupMockResponsesWithErrors(String issuer, int errorResponseCount) throws JsonProcessingException { @@ -431,7 +442,7 @@ class OAuth2ResourceServerAutoConfigurationTests { response.put("code_challenge_methods_supported", Collections.emptyList()); response.put("id_token_signing_alg_values_supported", Collections.emptyList()); response.put("issuer", issuer); - response.put("jwks_uri", "https://example.com/oauth2/v3/certs"); + response.put("jwks_uri", issuer + "/.well-known/jwks.json"); response.put("response_types_supported", Collections.emptyList()); response.put("revocation_endpoint", "https://example.com/o/oauth2/revoke"); response.put("scopes_supported", Collections.singletonList("openid")); diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index f90b89c523..59fec09af9 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1618,7 +1618,7 @@ bom { ] } } - library("Spring Security", "5.4.2") { + library("Spring Security", "5.5.0-M1") { group("org.springframework.security") { imports = [ "spring-security-bom"