Skip to content

Commit 05955a9

Browse files
committed
webauthn: introduce WebAuthnConfigurer#disableDefaultRegistrationPage
1 parent 6bf615a commit 05955a9

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public class WebAuthnConfigurer<H extends HttpSecurityBuilder<H>>
6161

6262
private Set<String> allowedOrigins = new HashSet<>();
6363

64+
private boolean disableDefaultRegistrationPage = false;
65+
6466
/**
6567
* The Relying Party id.
6668
* @param rpId the relying party id
@@ -102,6 +104,18 @@ public WebAuthnConfigurer<H> allowedOrigins(Set<String> allowedOrigins) {
102104
return this;
103105
}
104106

107+
/**
108+
* Configures whether the default webauthn registration should be disabled. Setting it
109+
* to {@code true} will prevent the configurer from registering the
110+
* {@link DefaultWebAuthnRegistrationPageGeneratingFilter}.
111+
* @param disable disable the default registration page if true, enable it otherwise
112+
* @return the {@link WebAuthnConfigurer} for further customization
113+
*/
114+
public WebAuthnConfigurer<H> disableDefaultRegistrationPage(boolean disable) {
115+
this.disableDefaultRegistrationPage = disable;
116+
return this;
117+
}
118+
105119
@Override
106120
public void configure(H http) throws Exception {
107121
UserDetailsService userDetailsService = getSharedOrBean(http, UserDetailsService.class).orElseGet(() -> {
@@ -119,19 +133,24 @@ public void configure(H http) throws Exception {
119133
http.addFilterBefore(webAuthnAuthnFilter, BasicAuthenticationFilter.class);
120134
http.addFilterAfter(new WebAuthnRegistrationFilter(userCredentials, rpOperations), AuthorizationFilter.class);
121135
http.addFilterBefore(new PublicKeyCredentialCreationOptionsFilter(rpOperations), AuthorizationFilter.class);
122-
http.addFilterAfter(new DefaultWebAuthnRegistrationPageGeneratingFilter(userEntities, userCredentials),
123-
AuthorizationFilter.class);
124136
http.addFilterBefore(new PublicKeyCredentialRequestOptionsFilter(rpOperations), AuthorizationFilter.class);
137+
125138
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http
126139
.getSharedObject(DefaultLoginPageGeneratingFilter.class);
127-
if (loginPageGeneratingFilter != null) {
140+
if (loginPageGeneratingFilter != null && loginPageGeneratingFilter.isEnabled()) {
128141
loginPageGeneratingFilter.setPasskeysEnabled(true);
129142
loginPageGeneratingFilter.setResolveHeaders((request) -> {
130143
CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
131144
return Map.of(csrfToken.getHeaderName(), csrfToken.getToken());
132145
});
133146
http.addFilter(DefaultResourcesFilter.webauthn());
134147
}
148+
149+
if (!this.disableDefaultRegistrationPage) {
150+
http.addFilterAfter(new DefaultWebAuthnRegistrationPageGeneratingFilter(userEntities, userCredentials),
151+
AuthorizationFilter.class);
152+
http.addFilter(DefaultResourcesFilter.webauthn());
153+
}
135154
}
136155

137156
private <C> Optional<C> getSharedOrBean(H http, Class<C> type) {

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ public void javascriptWhenWebauthnConfiguredThenServesJavascript() throws Except
5858
.andExpect(content().string(containsString("async function authenticate(")));
5959
}
6060

61+
@Test
62+
public void javascriptWhenWebauthnAndFormLoginThenDoesServesJavascript() throws Exception {
63+
this.spring.register(FormLoginAndNoDefaultRegistrationPageConfiguration.class).autowire();
64+
this.mvc.perform(get("/login/webauthn.js"))
65+
.andExpect(status().isOk())
66+
.andExpect(header().string("content-type", "text/javascript;charset=UTF-8"))
67+
.andExpect(content().string(containsString("async function authenticate(")));
68+
}
69+
70+
@Test
71+
public void javascriptWhenWebauthnAndNoDefaultRegistrationPageThenDoesNotServeJavascript() throws Exception {
72+
this.spring.register(NoDefaultRegistrationPageConfiguration.class).autowire();
73+
this.mvc.perform(get("/login/webauthn.js")).andExpect(status().isNotFound());
74+
}
75+
6176
@Configuration
6277
@EnableWebSecurity
6378
static class DefaultWebauthnConfiguration {
@@ -74,4 +89,40 @@ SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
7489

7590
}
7691

92+
@Configuration
93+
@EnableWebSecurity
94+
static class FormLoginAndNoDefaultRegistrationPageConfiguration {
95+
96+
@Bean
97+
UserDetailsService userDetailsService() {
98+
return new InMemoryUserDetailsManager();
99+
}
100+
101+
@Bean
102+
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
103+
return http.formLogin(Customizer.withDefaults())
104+
.webAuthn((webauthn) -> webauthn.disableDefaultRegistrationPage(true))
105+
.build();
106+
}
107+
108+
}
109+
110+
@Configuration
111+
@EnableWebSecurity
112+
static class NoDefaultRegistrationPageConfiguration {
113+
114+
@Bean
115+
UserDetailsService userDetailsService() {
116+
return new InMemoryUserDetailsManager();
117+
}
118+
119+
@Bean
120+
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
121+
return http.formLogin((login) -> login.loginPage("/custom-login-page"))
122+
.webAuthn((webauthn) -> webauthn.disableDefaultRegistrationPage(true))
123+
.build();
124+
}
125+
126+
}
127+
77128
}

0 commit comments

Comments
 (0)