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 41518ed191..c48827c92d 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 @@ -18,6 +18,7 @@ package org.springframework.security.config.annotation.web import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configurers.WebAuthnConfigurer +import org.springframework.security.web.webauthn.registration.PublicKeyCredentialCreationOptionsRepository /** * A Kotlin DSL to configure [HttpSecurity] webauthn using idiomatic Kotlin code. @@ -35,6 +36,7 @@ class WebAuthnDsl { var rpId: String? = null var allowedOrigins: Set? = null var disableDefaultRegistrationPage: Boolean? = false + var creationOptionsRepository: PublicKeyCredentialCreationOptionsRepository? = null internal fun get(): (WebAuthnConfigurer) -> Unit { return { webAuthn -> @@ -42,6 +44,7 @@ class WebAuthnDsl { rpId?.also { webAuthn.rpId(rpId) } allowedOrigins?.also { webAuthn.allowedOrigins(allowedOrigins) } disableDefaultRegistrationPage?.also { webAuthn.disableDefaultRegistrationPage(disableDefaultRegistrationPage!!) } + creationOptionsRepository?.also { webAuthn.creationOptionsRepository(creationOptionsRepository) } } } } 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 8bdee169f8..feb580e4b9 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 @@ -30,6 +30,7 @@ import org.springframework.security.core.userdetails.User import org.springframework.security.core.userdetails.UserDetailsService import org.springframework.security.provisioning.InMemoryUserDetailsManager import org.springframework.security.web.SecurityFilterChain +import org.springframework.security.web.webauthn.registration.HttpSessionPublicKeyCredentialCreationOptionsRepository import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.get import org.springframework.test.web.servlet.post @@ -58,6 +59,16 @@ class WebAuthnDslTests { } } + @Test + fun `explicit PublicKeyCredentialCreationOptionsRepository`() { + this.spring.register(ExplicitPublicKeyCredentialCreationOptionsRepositoryConfig::class.java).autowire() + + this.mockMvc.post("/test1") + .andExpect { + status { isForbidden() } + } + } + @Test fun `webauthn and formLogin configured with default registration page`() { spring.register(DefaultWebauthnConfig::class.java).autowire() @@ -128,6 +139,33 @@ class WebAuthnDslTests { } } + @Configuration + @EnableWebSecurity + open class ExplicitPublicKeyCredentialCreationOptionsRepositoryConfig { + @Bean + open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + http { + webAuthn { + rpName = "Spring Security Relying Party" + rpId = "example.com" + allowedOrigins = setOf("https://example.com") + creationOptionsRepository = HttpSessionPublicKeyCredentialCreationOptionsRepository() + } + } + return http.build() + } + + @Bean + open fun userDetailsService(): UserDetailsService { + val userDetails = User.withDefaultPasswordEncoder() + .username("rod") + .password("password") + .roles("USER") + .build() + return InMemoryUserDetailsManager(userDetails) + } + } + @Configuration @EnableWebSecurity open class WebauthnConfig {