Skip to content

Commit 372efe0

Browse files
committed
Add missing loginPage property to One-Time Token DSLs
This adds loginPage support to both servlet and reactive One-Time Token Kotlin DSLs. Closes: gh-19249 Signed-off-by: Andrey Litvitski <andrey1010102008@gmail.com>
1 parent 4a5379e commit 372efe0

4 files changed

Lines changed: 89 additions & 0 deletions

File tree

config/src/main/kotlin/org/springframework/security/config/annotation/web/OneTimeTokenLoginDsl.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import org.springframework.security.web.authentication.ott.OneTimeTokenGeneratio
3030
* A Kotlin DSL to configure [HttpSecurity] OAuth 2.0 login using idiomatic Kotlin code.
3131
*
3232
* @author Max Batischev
33+
* @author Andrey Litvitski
3334
* @since 6.4
3435
* @property tokenService configures the [OneTimeTokenService] used to generate and consume
3536
* @property authenticationConverter Use this [AuthenticationConverter] when converting incoming requests to an authentication
@@ -39,6 +40,8 @@ import org.springframework.security.web.authentication.ott.OneTimeTokenGeneratio
3940
* @property defaultSubmitPageUrl sets the URL that the default submit page will be generated
4041
* @property showDefaultSubmitPage configures whether the default one-time token submit page should be shown
4142
* @property loginProcessingUrl the URL to process the login request
43+
* @property loginPage the login page to redirect to if authentication is required (i.e.
44+
* "/login")
4245
* @property tokenGeneratingUrl the URL that a One-Time Token generate request will be processed
4346
* @property oneTimeTokenGenerationSuccessHandler the strategy to be used to handle generated one-time tokens
4447
* @property authenticationProvider the [AuthenticationProvider] to use when authenticating the user
@@ -52,6 +55,7 @@ class OneTimeTokenLoginDsl {
5255
var generateRequestResolver: GenerateOneTimeTokenRequestResolver? = null
5356
var defaultSubmitPageUrl: String? = null
5457
var loginProcessingUrl: String? = null
58+
var loginPage: String? = null
5559
var tokenGeneratingUrl: String? = null
5660
var showDefaultSubmitPage: Boolean? = true
5761
var oneTimeTokenGenerationSuccessHandler: OneTimeTokenGenerationSuccessHandler? = null
@@ -79,6 +83,7 @@ class OneTimeTokenLoginDsl {
7983
defaultSubmitPageUrl?.also { oneTimeTokenLoginConfigurer.defaultSubmitPageUrl(defaultSubmitPageUrl) }
8084
showDefaultSubmitPage?.also { oneTimeTokenLoginConfigurer.showDefaultSubmitPage(showDefaultSubmitPage!!) }
8185
loginProcessingUrl?.also { oneTimeTokenLoginConfigurer.loginProcessingUrl(loginProcessingUrl) }
86+
loginPage?.also { oneTimeTokenLoginConfigurer.loginPage((loginPage)) }
8287
tokenGeneratingUrl?.also { oneTimeTokenLoginConfigurer.tokenGeneratingUrl(tokenGeneratingUrl) }
8388
oneTimeTokenGenerationSuccessHandler?.also {
8489
oneTimeTokenLoginConfigurer.tokenGenerationSuccessHandler(

config/src/main/kotlin/org/springframework/security/config/web/server/ServerOneTimeTokenLoginDsl.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import org.springframework.security.web.server.context.ServerSecurityContextRepo
2929
* A Kotlin DSL to configure [ServerHttpSecurity] form login using idiomatic Kotlin code.
3030
*
3131
* @author Max Batischev
32+
* @author Andrey Litvitski
3233
* @since 6.4
3334
* @property tokenService configures the [ReactiveOneTimeTokenService] used to generate and consume
3435
* @property authenticationManager configures the [ReactiveAuthenticationManager] used to generate and consume
@@ -39,6 +40,8 @@ import org.springframework.security.web.server.context.ServerSecurityContextRepo
3940
* @property defaultSubmitPageUrl sets the URL that the default submit page will be generated
4041
* @property showDefaultSubmitPage configures whether the default one-time token submit page should be shown
4142
* @property loginProcessingUrl the URL to process the login request
43+
* @property loginPage the login page to redirect to if authentication is required (i.e.
44+
* "/login")
4245
* @property tokenGeneratingUrl the URL that a One-Time Token generate request will be processed
4346
* @property tokenGenerationSuccessHandler the strategy to be used to handle generated one-time tokens
4447
* @property securityContextRepository the [ServerSecurityContextRepository] used to save the [Authentication]. For the [SecurityContext] to be loaded on subsequent requests the [ReactorContextWebFilter] must be configured to be able to load the value (they are not implicitly linked).
@@ -55,6 +58,7 @@ class ServerOneTimeTokenLoginDsl {
5558
var generateRequestResolver: ServerGenerateOneTimeTokenRequestResolver? = null
5659
var defaultSubmitPageUrl: String? = null
5760
var loginProcessingUrl: String? = null
61+
var loginPage: String? = null
5862
var tokenGeneratingUrl: String? = null
5963
var showDefaultSubmitPage: Boolean? = true
6064

@@ -78,6 +82,7 @@ class ServerOneTimeTokenLoginDsl {
7882
defaultSubmitPageUrl?.also { oneTimeTokenLogin.defaultSubmitPageUrl(defaultSubmitPageUrl) }
7983
showDefaultSubmitPage?.also { oneTimeTokenLogin.showDefaultSubmitPage(showDefaultSubmitPage!!) }
8084
loginProcessingUrl?.also { oneTimeTokenLogin.loginProcessingUrl(loginProcessingUrl) }
85+
loginPage?.also { oneTimeTokenLogin.loginPage((loginPage)) }
8186
tokenGeneratingUrl?.also { oneTimeTokenLogin.tokenGeneratingUrl(tokenGeneratingUrl) }
8287
tokenGenerationSuccessHandler?.also {
8388
oneTimeTokenLogin.tokenGenerationSuccessHandler(

config/src/test/kotlin/org/springframework/security/config/annotation/web/OneTimeTokenLoginDslTests.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import java.time.Instant
5656
* Tests for [OneTimeTokenLoginDsl]
5757
*
5858
* @author Max Batischev
59+
* @author Andrey Litvitski
5960
*/
6061
@ExtendWith(SpringTestContextExtension::class)
6162
class OneTimeTokenLoginDslTests {
@@ -142,6 +143,17 @@ class OneTimeTokenLoginDslTests {
142143

143144
}
144145

146+
@Test
147+
fun `request when secure and custom login page then redirects to custom login page`() {
148+
spring.register(LoginPageConfig::class.java).autowire()
149+
150+
mockMvc.perform(MockMvcRequestBuilders.get("/"))
151+
.andExpectAll(
152+
MockMvcResultMatchers.status().isFound(),
153+
MockMvcResultMatchers.redirectedUrl("http://localhost/log-in")
154+
)
155+
}
156+
145157
private fun getLastToken(): OneTimeToken {
146158
val lastToken = spring.context
147159
.getBean(TestOneTimeTokenGenerationSuccessHandler::class.java).lastToken
@@ -244,6 +256,33 @@ class OneTimeTokenLoginDslTests {
244256
}
245257
}
246258

259+
@EnableWebSecurity
260+
@Configuration(proxyBeanMethods = false)
261+
@Import(UserDetailsServiceConfig::class)
262+
open class LoginPageConfig {
263+
264+
@Bean
265+
open fun securityFilterChain(
266+
http: HttpSecurity,
267+
ottSuccessHandler: OneTimeTokenGenerationSuccessHandler
268+
): SecurityFilterChain {
269+
http {
270+
authorizeHttpRequests {
271+
authorize(anyRequest, authenticated)
272+
}
273+
oneTimeTokenLogin {
274+
loginPage = "/log-in"
275+
oneTimeTokenGenerationSuccessHandler = ottSuccessHandler
276+
}
277+
}
278+
return http.build()
279+
}
280+
281+
@Bean
282+
open fun ottSuccessHandler() =
283+
TestOneTimeTokenGenerationSuccessHandler()
284+
}
285+
247286
@Configuration(proxyBeanMethods = false)
248287
open class UserDetailsServiceConfig {
249288

config/src/test/kotlin/org/springframework/security/config/web/server/ServerOneTimeTokenLoginDslTests.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import reactor.core.publisher.Mono
5252
* Tests for [ServerOneTimeTokenLoginDsl]
5353
*
5454
* @author Max Batischev
55+
* @author Andrey Litvitski
5556
*/
5657
@ExtendWith(SpringTestContextExtension::class)
5758
class ServerOneTimeTokenLoginDslTests {
@@ -176,10 +177,49 @@ class ServerOneTimeTokenLoginDslTests {
176177
// @formatter:on
177178
}
178179

180+
@Test
181+
fun `request when secure and custom login page then redirects to custom login page`() {
182+
spring.register(LoginPageConfig::class.java).autowire()
183+
184+
client.get()
185+
.uri("/")
186+
.exchange()
187+
.expectStatus().is3xxRedirection
188+
.expectHeader().valueEquals("Location", "/log-in")
189+
}
190+
179191
private fun lastToken():OneTimeToken? =
180192
spring.context.getBean(TestServerOneTimeTokenGenerationSuccessHandler::class.java)
181193
.lastToken
182194

195+
@Configuration
196+
@EnableWebFlux
197+
@EnableWebFluxSecurity
198+
@Import(UserDetailsServiceConfig::class)
199+
open class LoginPageConfig {
200+
201+
@Bean
202+
open fun springWebFilterChain(
203+
http: ServerHttpSecurity,
204+
ottSuccessHandler: ServerOneTimeTokenGenerationSuccessHandler
205+
): SecurityWebFilterChain {
206+
// @formatter:off
207+
return http {
208+
authorizeExchange {
209+
authorize(anyExchange, authenticated)
210+
}
211+
oneTimeTokenLogin {
212+
loginPage = "/log-in"
213+
tokenGenerationSuccessHandler = ottSuccessHandler
214+
}
215+
}
216+
// @formatter:on
217+
}
218+
219+
@Bean
220+
open fun ottSuccessHandler(): ServerOneTimeTokenGenerationSuccessHandler =
221+
TestServerOneTimeTokenGenerationSuccessHandler()
222+
}
183223

184224
@Configuration
185225
@EnableWebFlux

0 commit comments

Comments
 (0)