|
|
@@ -18,12 +18,15 @@ package org.springframework.security.config.annotation.web.configurers;
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
import org.junit.jupiter.api.extension.ExtendWith;
|
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
+import org.springframework.security.authentication.TestingAuthenticationToken;
|
|
|
import org.springframework.security.config.Customizer;
|
|
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
|
@@ -38,7 +41,10 @@ import org.springframework.test.web.servlet.MockMvc;
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
import static org.hamcrest.Matchers.containsString;
|
|
|
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
|
|
+import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
|
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
|
|
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
|
@@ -111,6 +117,42 @@ public class WebAuthnConfigurerTests {
|
|
|
.hasSize(1);
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ void webauthnWhenConfiguredDefaultsRpNameToRpId() throws Exception {
|
|
|
+ ObjectMapper mapper = new ObjectMapper();
|
|
|
+ this.spring.register(DefaultWebauthnConfiguration.class).autowire();
|
|
|
+ String response = this.mvc
|
|
|
+ .perform(post("/webauthn/register/options").with(csrf())
|
|
|
+ .with(authentication(new TestingAuthenticationToken("test", "ignored", "ROLE_user"))))
|
|
|
+ .andExpect(status().is2xxSuccessful())
|
|
|
+ .andReturn()
|
|
|
+ .getResponse()
|
|
|
+ .getContentAsString();
|
|
|
+
|
|
|
+ JsonNode parsedResponse = mapper.readTree(response);
|
|
|
+
|
|
|
+ assertThat(parsedResponse.get("rp").get("id").asText()).isEqualTo("example.com");
|
|
|
+ assertThat(parsedResponse.get("rp").get("name").asText()).isEqualTo("example.com");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void webauthnWhenRpNameConfiguredUsesRpName() throws Exception {
|
|
|
+ ObjectMapper mapper = new ObjectMapper();
|
|
|
+ this.spring.register(CustomRpNameWebauthnConfiguration.class).autowire();
|
|
|
+ String response = this.mvc
|
|
|
+ .perform(post("/webauthn/register/options").with(csrf())
|
|
|
+ .with(authentication(new TestingAuthenticationToken("test", "ignored", "ROLE_user"))))
|
|
|
+ .andExpect(status().is2xxSuccessful())
|
|
|
+ .andReturn()
|
|
|
+ .getResponse()
|
|
|
+ .getContentAsString();
|
|
|
+
|
|
|
+ JsonNode parsedResponse = mapper.readTree(response);
|
|
|
+
|
|
|
+ assertThat(parsedResponse.get("rp").get("id").asText()).isEqualTo("example.com");
|
|
|
+ assertThat(parsedResponse.get("rp").get("name").asText()).isEqualTo("Test RP Name");
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
public void webauthnWhenConfiguredAndFormLoginThenDoesServesJavascript() throws Exception {
|
|
|
this.spring.register(FormLoginAndNoDefaultRegistrationPageConfiguration.class).autowire();
|
|
|
@@ -137,7 +179,27 @@ public class WebAuthnConfigurerTests {
|
|
|
|
|
|
@Bean
|
|
|
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
|
- return http.formLogin(Customizer.withDefaults()).webAuthn(Customizer.withDefaults()).build();
|
|
|
+ return http.formLogin(Customizer.withDefaults())
|
|
|
+ .webAuthn((webauthn) -> webauthn.rpId("example.com"))
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Configuration
|
|
|
+ @EnableWebSecurity
|
|
|
+ static class CustomRpNameWebauthnConfiguration {
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ UserDetailsService userDetailsService() {
|
|
|
+ return new InMemoryUserDetailsManager();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Bean
|
|
|
+ SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
|
+ return http.formLogin(Customizer.withDefaults())
|
|
|
+ .webAuthn((webauthn) -> webauthn.rpId("example.com").rpName("Test RP Name"))
|
|
|
+ .build();
|
|
|
}
|
|
|
|
|
|
}
|