Skip to content

Commit 6471a32

Browse files
committed
Merge branch '6.5.x'
Closes gh-18132
2 parents 20ae9dc + c1e9e10 commit 6471a32

File tree

4 files changed

+63
-8
lines changed

4 files changed

+63
-8
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
@@ -2052,7 +2052,6 @@ public HttpSecurity securityMatcher(String... patterns) {
20522052
* http
20532053
* // ...
20542054
* .webAuthn((webAuthn) -> webAuthn
2055-
* .rpName("Spring Security Relying Party")
20562055
* .rpId("example.com")
20572056
* .allowedOrigins("https://example.com")
20582057
* );

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
@@ -257,9 +257,10 @@ private WebAuthnRelyingPartyOperations webAuthnRelyingPartyOperations(
257257
PublicKeyCredentialUserEntityRepository userEntities, UserCredentialRepository userCredentials) {
258258
Optional<WebAuthnRelyingPartyOperations> webauthnOperationsBean = getBeanOrNull(
259259
WebAuthnRelyingPartyOperations.class);
260-
return webauthnOperationsBean.orElseGet(() -> new Webauthn4JRelyingPartyOperations(userEntities,
261-
userCredentials, PublicKeyCredentialRpEntity.builder().id(this.rpId).name(this.rpName).build(),
262-
this.allowedOrigins));
260+
String rpName = (this.rpName != null) ? this.rpName : this.rpId;
261+
return webauthnOperationsBean
262+
.orElseGet(() -> new Webauthn4JRelyingPartyOperations(userEntities, userCredentials,
263+
PublicKeyCredentialRpEntity.builder().id(this.rpId).name(rpName).build(), this.allowedOrigins));
263264
}
264265

265266
}

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

Lines changed: 59 additions & 2 deletions
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

@@ -54,6 +56,8 @@
5456
import static org.mockito.BDDMockito.given;
5557
import static org.mockito.BDDMockito.willAnswer;
5658
import static org.mockito.Mockito.mock;
59+
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
60+
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
5761
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
5862
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
5963
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@@ -137,6 +141,42 @@ public void webauthnWhenFormLoginAndDefaultRegistrationPageConfiguredThenNoDupli
137141
.hasSize(1);
138142
}
139143

144+
@Test
145+
void webauthnWhenConfiguredDefaultsRpNameToRpId() throws Exception {
146+
ObjectMapper mapper = new ObjectMapper();
147+
this.spring.register(DefaultWebauthnConfiguration.class).autowire();
148+
String response = this.mvc
149+
.perform(post("/webauthn/register/options").with(csrf())
150+
.with(authentication(new TestingAuthenticationToken("test", "ignored", "ROLE_user"))))
151+
.andExpect(status().is2xxSuccessful())
152+
.andReturn()
153+
.getResponse()
154+
.getContentAsString();
155+
156+
JsonNode parsedResponse = mapper.readTree(response);
157+
158+
assertThat(parsedResponse.get("rp").get("id").asText()).isEqualTo("example.com");
159+
assertThat(parsedResponse.get("rp").get("name").asText()).isEqualTo("example.com");
160+
}
161+
162+
@Test
163+
void webauthnWhenRpNameConfiguredUsesRpName() throws Exception {
164+
ObjectMapper mapper = new ObjectMapper();
165+
this.spring.register(CustomRpNameWebauthnConfiguration.class).autowire();
166+
String response = this.mvc
167+
.perform(post("/webauthn/register/options").with(csrf())
168+
.with(authentication(new TestingAuthenticationToken("test", "ignored", "ROLE_user"))))
169+
.andExpect(status().is2xxSuccessful())
170+
.andReturn()
171+
.getResponse()
172+
.getContentAsString();
173+
174+
JsonNode parsedResponse = mapper.readTree(response);
175+
176+
assertThat(parsedResponse.get("rp").get("id").asText()).isEqualTo("example.com");
177+
assertThat(parsedResponse.get("rp").get("name").asText()).isEqualTo("Test RP Name");
178+
}
179+
140180
@Test
141181
public void webauthnWhenConfiguredAndFormLoginThenDoesServesJavascript() throws Exception {
142182
this.spring.register(FormLoginAndNoDefaultRegistrationPageConfiguration.class).autowire();
@@ -334,15 +374,32 @@ SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
334374
http
335375
.formLogin(Customizer.withDefaults())
336376
.webAuthn((authn) -> authn
337-
.rpId("spring.io")
338-
.rpName("spring")
377+
.rpId("example.com")
339378
);
340379
// @formatter:on
341380
return http.build();
342381
}
343382

344383
}
345384

385+
@Configuration
386+
@EnableWebSecurity
387+
static class CustomRpNameWebauthnConfiguration {
388+
389+
@Bean
390+
UserDetailsService userDetailsService() {
391+
return new InMemoryUserDetailsManager();
392+
}
393+
394+
@Bean
395+
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
396+
return http.formLogin(Customizer.withDefaults())
397+
.webAuthn((webauthn) -> webauthn.rpId("example.com").rpName("Test RP Name"))
398+
.build();
399+
}
400+
401+
}
402+
346403
@Configuration
347404
@EnableWebSecurity
348405
static class NoFormLoginAndDefaultRegistrationPageConfiguration {

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)