diff --git a/config/src/main/kotlin/org/springframework/security/config/web/servlet/FormLoginDsl.kt b/config/src/main/kotlin/org/springframework/security/config/web/servlet/FormLoginDsl.kt index 072d54877c..afa40f2281 100644 --- a/config/src/main/kotlin/org/springframework/security/config/web/servlet/FormLoginDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/web/servlet/FormLoginDsl.kt @@ -16,11 +16,13 @@ package org.springframework.security.config.web.servlet +import org.springframework.security.authentication.AuthenticationDetailsSource import org.springframework.security.config.annotation.web.HttpSecurityBuilder import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer import org.springframework.security.web.authentication.AuthenticationFailureHandler import org.springframework.security.web.authentication.AuthenticationSuccessHandler +import javax.servlet.http.HttpServletRequest /** * A Kotlin DSL to configure [HttpSecurity] form login using idiomatic Kotlin code. @@ -46,6 +48,7 @@ class FormLoginDsl { var failureUrl: String? = null var loginProcessingUrl: String? = null var permitAll: Boolean? = null + var authenticationDetailsSource: AuthenticationDetailsSource? = null private var defaultSuccessUrlOption: Pair? = null @@ -81,6 +84,7 @@ class FormLoginDsl { } authenticationSuccessHandler?.also { login.successHandler(authenticationSuccessHandler) } authenticationFailureHandler?.also { login.failureHandler(authenticationFailureHandler) } + authenticationDetailsSource?.also { login.authenticationDetailsSource(authenticationDetailsSource) } } } } diff --git a/config/src/test/kotlin/org/springframework/security/config/web/servlet/FormLoginDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/web/servlet/FormLoginDslTests.kt index 5af6f0a3e7..16783f1307 100644 --- a/config/src/test/kotlin/org/springframework/security/config/web/servlet/FormLoginDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/web/servlet/FormLoginDslTests.kt @@ -16,10 +16,14 @@ package org.springframework.security.config.web.servlet +import io.mockk.every +import io.mockk.mockkObject +import io.mockk.verify import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.annotation.Configuration +import org.springframework.security.authentication.AuthenticationDetailsSource import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.config.annotation.web.builders.HttpSecurity import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity @@ -36,6 +40,7 @@ import org.springframework.test.web.servlet.get import org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.web.bind.annotation.GetMapping +import javax.servlet.http.HttpServletRequest /** * Tests for [FormLoginDsl] @@ -280,6 +285,42 @@ class FormLoginDslTests { } } + @Test + fun `form login when custom authentication details source then used`() { + this.spring + .register(CustomAuthenticationDetailsSourceConfig::class.java, UserConfig::class.java) + .autowire() + mockkObject(CustomAuthenticationDetailsSourceConfig.AUTHENTICATION_DETAILS_SOURCE) + every { + CustomAuthenticationDetailsSourceConfig.AUTHENTICATION_DETAILS_SOURCE.buildDetails(any()) + } returns Any() + + this.mockMvc.perform(formLogin()) + .andExpect { + status().isFound + redirectedUrl("/") + } + + verify(exactly = 1) { CustomAuthenticationDetailsSourceConfig.AUTHENTICATION_DETAILS_SOURCE.buildDetails(any()) } + } + + @EnableWebSecurity + open class CustomAuthenticationDetailsSourceConfig : WebSecurityConfigurerAdapter() { + + companion object { + val AUTHENTICATION_DETAILS_SOURCE: AuthenticationDetailsSource = + AuthenticationDetailsSource { Any() } + } + + override fun configure(http: HttpSecurity) { + http { + formLogin { + authenticationDetailsSource = AUTHENTICATION_DETAILS_SOURCE + } + } + } + } + @Configuration open class UserConfig { @Autowired