mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-11-10 19:48:50 +00:00
Merge branch '6.4.x' into 6.5.x
Closes gh-18131
This commit is contained in:
commit
c1e9e10bf0
@ -3758,7 +3758,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||||||
* http
|
* http
|
||||||
* // ...
|
* // ...
|
||||||
* .webAuthn((webAuthn) -> webAuthn
|
* .webAuthn((webAuthn) -> webAuthn
|
||||||
* .rpName("Spring Security Relying Party")
|
|
||||||
* .rpId("example.com")
|
* .rpId("example.com")
|
||||||
* .allowedOrigins("https://example.com")
|
* .allowedOrigins("https://example.com")
|
||||||
* );
|
* );
|
||||||
|
|||||||
@ -243,9 +243,10 @@ public class WebAuthnConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
PublicKeyCredentialUserEntityRepository userEntities, UserCredentialRepository userCredentials) {
|
PublicKeyCredentialUserEntityRepository userEntities, UserCredentialRepository userCredentials) {
|
||||||
Optional<WebAuthnRelyingPartyOperations> webauthnOperationsBean = getBeanOrNull(
|
Optional<WebAuthnRelyingPartyOperations> webauthnOperationsBean = getBeanOrNull(
|
||||||
WebAuthnRelyingPartyOperations.class);
|
WebAuthnRelyingPartyOperations.class);
|
||||||
return webauthnOperationsBean.orElseGet(() -> new Webauthn4JRelyingPartyOperations(userEntities,
|
String rpName = (this.rpName != null) ? this.rpName : this.rpId;
|
||||||
userCredentials, PublicKeyCredentialRpEntity.builder().id(this.rpId).name(this.rpName).build(),
|
return webauthnOperationsBean
|
||||||
this.allowedOrigins));
|
.orElseGet(() -> new Webauthn4JRelyingPartyOperations(userEntities, userCredentials,
|
||||||
|
PublicKeyCredentialRpEntity.builder().id(this.rpId).name(rpName).build(), this.allowedOrigins));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,8 @@ package org.springframework.security.config.annotation.web.configurers;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
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.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
@ -52,6 +54,8 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
import static org.mockito.BDDMockito.willAnswer;
|
import static org.mockito.BDDMockito.willAnswer;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
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.get;
|
||||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
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.content;
|
||||||
@ -127,6 +131,42 @@ public class WebAuthnConfigurerTests {
|
|||||||
.hasSize(1);
|
.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
|
@Test
|
||||||
public void webauthnWhenConfiguredAndFormLoginThenDoesServesJavascript() throws Exception {
|
public void webauthnWhenConfiguredAndFormLoginThenDoesServesJavascript() throws Exception {
|
||||||
this.spring.register(FormLoginAndNoDefaultRegistrationPageConfiguration.class).autowire();
|
this.spring.register(FormLoginAndNoDefaultRegistrationPageConfiguration.class).autowire();
|
||||||
@ -300,7 +340,27 @@ public class WebAuthnConfigurerTests {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,7 +65,6 @@ SecurityFilterChain filterChain(HttpSecurity http) {
|
|||||||
// ...
|
// ...
|
||||||
.formLogin(withDefaults())
|
.formLogin(withDefaults())
|
||||||
.webAuthn((webAuthn) -> webAuthn
|
.webAuthn((webAuthn) -> webAuthn
|
||||||
.rpName("Spring Security Relying Party")
|
|
||||||
.rpId("example.com")
|
.rpId("example.com")
|
||||||
.allowedOrigins("https://example.com")
|
.allowedOrigins("https://example.com")
|
||||||
// optional properties
|
// optional properties
|
||||||
@ -96,7 +95,6 @@ open fun filterChain(http: HttpSecurity): SecurityFilterChain {
|
|||||||
// ...
|
// ...
|
||||||
http {
|
http {
|
||||||
webAuthn {
|
webAuthn {
|
||||||
rpName = "Spring Security Relying Party"
|
|
||||||
rpId = "example.com"
|
rpId = "example.com"
|
||||||
allowedOrigins = setOf("https://example.com")
|
allowedOrigins = setOf("https://example.com")
|
||||||
// optional properties
|
// optional properties
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user