From 882766e54fed3c62a4ab7f8e4f39f945d90905f4 Mon Sep 17 00:00:00 2001 From: Max Batischev Date: Sat, 11 Jan 2025 11:56:39 +0300 Subject: [PATCH 1/2] Fix Kotlin webAuthn {} Fixes the default configuration for WebAuthn Kotlin DSL Closes gh-16338 Signed-off-by: Max Batischev --- .../config/annotation/web/WebAuthnDsl.kt | 11 +++--- .../config/annotation/web/WebAuthnDslTests.kt | 39 ++++++++++++++++++- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/WebAuthnDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/WebAuthnDsl.kt index 1624817431..c8296f367d 100644 --- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/WebAuthnDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/WebAuthnDsl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.springframework.security.config.annotation.web.configurers.WebAuthnCo * @property the allowed origins * @since 6.4 * @author Rob Winch + * @author Max Batischev */ @SecurityMarker class WebAuthnDsl { @@ -34,10 +35,10 @@ class WebAuthnDsl { var allowedOrigins: Set? = null internal fun get(): (WebAuthnConfigurer) -> Unit { - return { webAuthn -> webAuthn - .rpId(rpId) - .rpName(rpName) - .allowedOrigins(allowedOrigins); + return { webAuthn -> + rpName?.also { webAuthn.rpName(rpName) } + rpId?.also { webAuthn.rpId(rpId) } + allowedOrigins?.also { webAuthn.allowedOrigins(allowedOrigins) } } } } diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/WebAuthnDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/WebAuthnDslTests.kt index c0705e50bc..023314cdc3 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/WebAuthnDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/WebAuthnDslTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.security.config.annotation.web +import org.hamcrest.Matchers import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired @@ -30,7 +31,9 @@ import org.springframework.security.core.userdetails.UserDetailsService import org.springframework.security.provisioning.InMemoryUserDetailsManager import org.springframework.security.web.SecurityFilterChain import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.get import org.springframework.test.web.servlet.post +import org.springframework.test.web.servlet.result.MockMvcResultMatchers /** * Tests for [WebAuthnDsl] @@ -55,6 +58,40 @@ class WebAuthnDslTests { } } + @Test + fun `webauthn and formLogin configured with default registration page`() { + spring.register(DefaultWebauthnConfig::class.java).autowire() + + this.mockMvc.get("/login/webauthn.js") + .andExpect { + MockMvcResultMatchers.status().isOk + header { + string("content-type", "text/javascript;charset=UTF-8") + } + content { + string(Matchers.containsString("async function authenticate(")) + } + } + } + + @Configuration + @EnableWebSecurity + open class DefaultWebauthnConfig { + @Bean + open fun userDetailsService(): UserDetailsService = + InMemoryUserDetailsManager() + + + @Bean + open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + http{ + formLogin { } + webAuthn { } + } + return http.build() + } + } + @Configuration @EnableWebSecurity open class WebauthnConfig { From decf4def95600075faacb7b06c48fcf841bb57f1 Mon Sep 17 00:00:00 2001 From: Max Batischev Date: Sat, 11 Jan 2025 12:02:46 +0300 Subject: [PATCH 2/2] Add Support disableDefaultRegistrationPage to WebAuthnDsl Closes gh-16395 Signed-off-by: Max Batischev --- .../config/annotation/web/WebAuthnDsl.kt | 3 ++ .../config/annotation/web/WebAuthnDslTests.kt | 36 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/WebAuthnDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/WebAuthnDsl.kt index c8296f367d..f1a9600f00 100644 --- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/WebAuthnDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/WebAuthnDsl.kt @@ -24,6 +24,7 @@ import org.springframework.security.config.annotation.web.configurers.WebAuthnCo * @property rpName the relying party name * @property rpId the relying party id * @property the allowed origins + * @property disableDefaultRegistrationPage disable default webauthn registration page * @since 6.4 * @author Rob Winch * @author Max Batischev @@ -33,12 +34,14 @@ class WebAuthnDsl { var rpName: String? = null var rpId: String? = null var allowedOrigins: Set? = null + var disableDefaultRegistrationPage: Boolean? = false internal fun get(): (WebAuthnConfigurer) -> Unit { return { webAuthn -> rpName?.also { webAuthn.rpName(rpName) } rpId?.also { webAuthn.rpId(rpId) } allowedOrigins?.also { webAuthn.allowedOrigins(allowedOrigins) } + disableDefaultRegistrationPage?.also { webAuthn.disableDefaultRegistrationPage(disableDefaultRegistrationPage!!) } } } } diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/WebAuthnDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/WebAuthnDslTests.kt index 023314cdc3..8bdee169f8 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/WebAuthnDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/WebAuthnDslTests.kt @@ -74,6 +74,42 @@ class WebAuthnDslTests { } } + @Test + fun `webauthn and formLogin configured with disabled default registration page`() { + spring.register(FormLoginAndNoDefaultRegistrationPageConfiguration::class.java).autowire() + + this.mockMvc.get("/login/webauthn.js") + .andExpect { + MockMvcResultMatchers.status().isOk + header { + string("content-type", "text/javascript;charset=UTF-8") + } + content { + string(Matchers.containsString("async function authenticate(")) + } + } + } + + @Configuration + @EnableWebSecurity + open class FormLoginAndNoDefaultRegistrationPageConfiguration { + @Bean + open fun userDetailsService(): UserDetailsService = + InMemoryUserDetailsManager() + + + @Bean + open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + http{ + formLogin { } + webAuthn { + disableDefaultRegistrationPage = true + } + } + return http.build() + } + } + @Configuration @EnableWebSecurity open class DefaultWebauthnConfig {