Skip to content

Commit c1e9e10

Browse files
committed
Merge branch '6.4.x' into 6.5.x
Closes gh-18131
2 parents 8fa2fc0 + fed6df5 commit c1e9e10

File tree

4 files changed

+65
-7
lines changed

4 files changed

+65
-7
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3758,7 +3758,6 @@ public HttpSecurity securityMatcher(String... patterns) {
37583758
* http
37593759
* // ...
37603760
* .webAuthn((webAuthn) -> webAuthn
3761-
* .rpName("Spring Security Relying Party")
37623761
* .rpId("example.com")
37633762
* .allowedOrigins("https://example.com")
37643763
* );

config/src/main/java/org/springframework/security/config/annotation/web/configurers/WebAuthnConfigurer.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,10 @@ private WebAuthnRelyingPartyOperations webAuthnRelyingPartyOperations(
243243
PublicKeyCredentialUserEntityRepository userEntities, UserCredentialRepository userCredentials) {
244244
Optional<WebAuthnRelyingPartyOperations> webauthnOperationsBean = getBeanOrNull(
245245
WebAuthnRelyingPartyOperations.class);
246-
return webauthnOperationsBean.orElseGet(() -> new Webauthn4JRelyingPartyOperations(userEntities,
247-
userCredentials, PublicKeyCredentialRpEntity.builder().id(this.rpId).name(this.rpName).build(),
248-
this.allowedOrigins));
246+
String rpName = (this.rpName != null) ? this.rpName : this.rpId;
247+
return webauthnOperationsBean
248+
.orElseGet(() -> new Webauthn4JRelyingPartyOperations(userEntities, userCredentials,
249+
PublicKeyCredentialRpEntity.builder().id(this.rpId).name(rpName).build(), this.allowedOrigins));
249250
}
250251

251252
}

config/src/test/java/org/springframework/security/config/annotation/web/configurers/WebAuthnConfigurerTests.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.nio.charset.StandardCharsets;
2020
import java.util.List;
2121

22+
import com.fasterxml.jackson.databind.JsonNode;
23+
import com.fasterxml.jackson.databind.ObjectMapper;
2224
import org.junit.jupiter.api.Test;
2325
import org.junit.jupiter.api.extension.ExtendWith;
2426

@@ -52,6 +54,8 @@
5254
import static org.mockito.BDDMockito.given;
5355
import static org.mockito.BDDMockito.willAnswer;
5456
import static org.mockito.Mockito.mock;
57+
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
58+
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
5559
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
5660
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
5761
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@@ -127,6 +131,42 @@ public void webauthnWhenFormLoginAndDefaultRegistrationPageConfiguredThenNoDupli
127131
.hasSize(1);
128132
}
129133

134+
@Test
135+
void webauthnWhenConfiguredDefaultsRpNameToRpId() throws Exception {
136+
ObjectMapper mapper = new ObjectMapper();
137+
this.spring.register(DefaultWebauthnConfiguration.class).autowire();
138+
String response = this.mvc
139+
.perform(post("/webauthn/register/options").with(csrf())
140+
.with(authentication(new TestingAuthenticationToken("test", "ignored", "ROLE_user"))))
141+
.andExpect(status().is2xxSuccessful())
142+
.andReturn()
143+
.getResponse()
144+
.getContentAsString();
145+
146+
JsonNode parsedResponse = mapper.readTree(response);
147+
148+
assertThat(parsedResponse.get("rp").get("id").asText()).isEqualTo("example.com");
149+
assertThat(parsedResponse.get("rp").get("name").asText()).isEqualTo("example.com");
150+
}
151+
152+
@Test
153+
void webauthnWhenRpNameConfiguredUsesRpName() throws Exception {
154+
ObjectMapper mapper = new ObjectMapper();
155+
this.spring.register(CustomRpNameWebauthnConfiguration.class).autowire();
156+
String response = this.mvc
157+
.perform(post("/webauthn/register/options").with(csrf())
158+
.with(authentication(new TestingAuthenticationToken("test", "ignored", "ROLE_user"))))
159+
.andExpect(status().is2xxSuccessful())
160+
.andReturn()
161+
.getResponse()
162+
.getContentAsString();
163+
164+
JsonNode parsedResponse = mapper.readTree(response);
165+
166+
assertThat(parsedResponse.get("rp").get("id").asText()).isEqualTo("example.com");
167+
assertThat(parsedResponse.get("rp").get("name").asText()).isEqualTo("Test RP Name");
168+
}
169+
130170
@Test
131171
public void webauthnWhenConfiguredAndFormLoginThenDoesServesJavascript() throws Exception {
132172
this.spring.register(FormLoginAndNoDefaultRegistrationPageConfiguration.class).autowire();
@@ -300,7 +340,27 @@ UserDetailsService userDetailsService() {
300340

301341
@Bean
302342
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
303-
return http.formLogin(Customizer.withDefaults()).webAuthn(Customizer.withDefaults()).build();
343+
return http.formLogin(Customizer.withDefaults())
344+
.webAuthn((webauthn) -> webauthn.rpId("example.com"))
345+
.build();
346+
}
347+
348+
}
349+
350+
@Configuration
351+
@EnableWebSecurity
352+
static class CustomRpNameWebauthnConfiguration {
353+
354+
@Bean
355+
UserDetailsService userDetailsService() {
356+
return new InMemoryUserDetailsManager();
357+
}
358+
359+
@Bean
360+
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
361+
return http.formLogin(Customizer.withDefaults())
362+
.webAuthn((webauthn) -> webauthn.rpId("example.com").rpName("Test RP Name"))
363+
.build();
304364
}
305365

306366
}

docs/modules/ROOT/pages/servlet/authentication/passkeys.adoc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ SecurityFilterChain filterChain(HttpSecurity http) {
6565
// ...
6666
.formLogin(withDefaults())
6767
.webAuthn((webAuthn) -> webAuthn
68-
.rpName("Spring Security Relying Party")
6968
.rpId("example.com")
7069
.allowedOrigins("https://example.com")
7170
// optional properties
@@ -96,7 +95,6 @@ open fun filterChain(http: HttpSecurity): SecurityFilterChain {
9695
// ...
9796
http {
9897
webAuthn {
99-
rpName = "Spring Security Relying Party"
10098
rpId = "example.com"
10199
allowedOrigins = setOf("https://example.com")
102100
// optional properties

0 commit comments

Comments
 (0)