mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-23 12:32:13 +00:00
TestServerOneTimeTokenGenerationSuccessHandler.lastToken to non-static variable
Signed-off-by: Max Batischev <mblancer@mail.ru>
This commit is contained in:
parent
be81377235
commit
9676739c88
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2024 the original author or authors.
|
* Copyright 2002-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -21,6 +21,8 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.ArgumentMatchers;
|
||||||
|
import org.mockito.Mockito;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -40,6 +42,8 @@ import org.springframework.security.core.userdetails.User;
|
|||||||
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers;
|
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers;
|
||||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||||
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
|
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
|
||||||
|
import org.springframework.security.web.server.authentication.ott.DefaultServerGenerateOneTimeTokenRequestResolver;
|
||||||
|
import org.springframework.security.web.server.authentication.ott.ServerGenerateOneTimeTokenRequestResolver;
|
||||||
import org.springframework.security.web.server.authentication.ott.ServerOneTimeTokenGenerationSuccessHandler;
|
import org.springframework.security.web.server.authentication.ott.ServerOneTimeTokenGenerationSuccessHandler;
|
||||||
import org.springframework.security.web.server.authentication.ott.ServerRedirectOneTimeTokenGenerationSuccessHandler;
|
import org.springframework.security.web.server.authentication.ott.ServerRedirectOneTimeTokenGenerationSuccessHandler;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
@ -49,6 +53,8 @@ import org.springframework.web.server.ServerWebExchange;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatException;
|
import static org.assertj.core.api.Assertions.assertThatException;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ServerHttpSecurity.OneTimeTokenLoginSpec}
|
* Tests for {@link ServerHttpSecurity.OneTimeTokenLoginSpec}
|
||||||
@ -107,7 +113,7 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
.expectHeader().valueEquals("Location", "/login/ott");
|
.expectHeader().valueEquals("Location", "/login/ott");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
String token = TestServerOneTimeTokenGenerationSuccessHandler.lastToken.getTokenValue();
|
String token = getLastToken().getTokenValue();
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
@ -143,7 +149,7 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
.expectHeader().valueEquals("Location", "/redirected");
|
.expectHeader().valueEquals("Location", "/redirected");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
String token = TestServerOneTimeTokenGenerationSuccessHandler.lastToken.getTokenValue();
|
String token = getLastToken().getTokenValue();
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
@ -179,7 +185,7 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
.expectHeader().valueEquals("Location", "/login/ott");
|
.expectHeader().valueEquals("Location", "/login/ott");
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
String token = TestServerOneTimeTokenGenerationSuccessHandler.lastToken.getTokenValue();
|
String token = getLastToken().getTokenValue();
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
@ -268,18 +274,49 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
assertThat(response.contains(GENERATE_OTT_PART)).isTrue();
|
assertThat(response.contains(GENERATE_OTT_PART)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private OneTimeToken getLastToken() {
|
||||||
|
OneTimeToken lastToken = this.spring.getContext()
|
||||||
|
.getBean(TestServerOneTimeTokenGenerationSuccessHandler.class).lastToken;
|
||||||
|
return lastToken;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void oneTimeTokenWhenNoOneTimeTokenGenerationSuccessHandlerThenException() {
|
void oneTimeTokenWhenNoOneTimeTokenGenerationSuccessHandlerThenException() {
|
||||||
assertThatException()
|
assertThatException()
|
||||||
.isThrownBy(() -> this.spring.register(OneTimeTokenNotGeneratedOttHandlerConfig.class).autowire())
|
.isThrownBy(() -> this.spring.register(OneTimeTokenNotGeneratedOttHandlerConfig.class).autowire())
|
||||||
.havingRootCause()
|
.havingRootCause()
|
||||||
.isInstanceOf(IllegalStateException.class)
|
.isInstanceOf(IllegalStateException.class)
|
||||||
.withMessage("""
|
.withMessage("""
|
||||||
A ServerOneTimeTokenGenerationSuccessHandler is required to enable oneTimeTokenLogin().
|
A ServerOneTimeTokenGenerationSuccessHandler is required to enable oneTimeTokenLogin().
|
||||||
Please provide it as a bean or pass it to the oneTimeTokenLogin() DSL.
|
Please provide it as a bean or pass it to the oneTimeTokenLogin() DSL.
|
||||||
""");
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void oneTimeTokenWhenCustomRequestResolverSetThenCustomResolverUse() {
|
||||||
|
this.spring.register(OneTimeTokenConfigWithCustomRequestResolver.class).autowire();
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
this.client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
|
.post()
|
||||||
|
.uri((uriBuilder) -> uriBuilder
|
||||||
|
.path("/ott/generate")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
|
.body(BodyInserters.fromFormData("username", "user"))
|
||||||
|
.exchange()
|
||||||
|
.expectStatus()
|
||||||
|
.is3xxRedirection()
|
||||||
|
.expectHeader().valueEquals("Location", "/login/ott");
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
ServerGenerateOneTimeTokenRequestResolver resolver = this.spring.getContext()
|
||||||
|
.getBean(ServerGenerateOneTimeTokenRequestResolver.class);
|
||||||
|
|
||||||
|
verify(resolver, times(1)).resolve(ArgumentMatchers.any(ServerWebExchange.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@EnableWebFlux
|
@EnableWebFlux
|
||||||
@EnableWebFluxSecurity
|
@EnableWebFluxSecurity
|
||||||
@ -287,7 +324,8 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
static class OneTimeTokenDefaultConfig {
|
static class OneTimeTokenDefaultConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http,
|
||||||
|
ServerOneTimeTokenGenerationSuccessHandler ottSuccessHandler) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeExchange((authorize) -> authorize
|
.authorizeExchange((authorize) -> authorize
|
||||||
@ -295,12 +333,17 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
.authenticated()
|
.authenticated()
|
||||||
)
|
)
|
||||||
.oneTimeTokenLogin((ott) -> ott
|
.oneTimeTokenLogin((ott) -> ott
|
||||||
.tokenGenerationSuccessHandler(new TestServerOneTimeTokenGenerationSuccessHandler())
|
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
||||||
);
|
);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
TestServerOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
|
||||||
|
return new TestServerOneTimeTokenGenerationSuccessHandler();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ -310,7 +353,8 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
static class OneTimeTokenDifferentUrlsConfig {
|
static class OneTimeTokenDifferentUrlsConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
|
SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http,
|
||||||
|
ServerOneTimeTokenGenerationSuccessHandler ottSuccessHandler) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeExchange((authorize) -> authorize
|
.authorizeExchange((authorize) -> authorize
|
||||||
@ -319,7 +363,7 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
)
|
)
|
||||||
.oneTimeTokenLogin((ott) -> ott
|
.oneTimeTokenLogin((ott) -> ott
|
||||||
.tokenGeneratingUrl("/generateurl")
|
.tokenGeneratingUrl("/generateurl")
|
||||||
.tokenGenerationSuccessHandler(new TestServerOneTimeTokenGenerationSuccessHandler("/redirected"))
|
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
||||||
.loginProcessingUrl("/loginprocessingurl")
|
.loginProcessingUrl("/loginprocessingurl")
|
||||||
.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/authenticated"))
|
.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/authenticated"))
|
||||||
);
|
);
|
||||||
@ -327,6 +371,11 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
TestServerOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
|
||||||
|
return new TestServerOneTimeTokenGenerationSuccessHandler("/redirected");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ -336,7 +385,8 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
static class OneTimeTokenFormLoginConfig {
|
static class OneTimeTokenFormLoginConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http) {
|
SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http,
|
||||||
|
ServerOneTimeTokenGenerationSuccessHandler ottSuccessHandler) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.authorizeExchange((authorize) -> authorize
|
.authorizeExchange((authorize) -> authorize
|
||||||
@ -345,12 +395,17 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
)
|
)
|
||||||
.formLogin(Customizer.withDefaults())
|
.formLogin(Customizer.withDefaults())
|
||||||
.oneTimeTokenLogin((ott) -> ott
|
.oneTimeTokenLogin((ott) -> ott
|
||||||
.tokenGenerationSuccessHandler(new TestServerOneTimeTokenGenerationSuccessHandler())
|
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
||||||
);
|
);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
TestServerOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
|
||||||
|
return new TestServerOneTimeTokenGenerationSuccessHandler();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ -385,10 +440,44 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@EnableWebFlux
|
||||||
|
@EnableWebFluxSecurity
|
||||||
|
@Import(UserDetailsServiceConfig.class)
|
||||||
|
static class OneTimeTokenConfigWithCustomRequestResolver {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http,
|
||||||
|
ServerOneTimeTokenGenerationSuccessHandler ottSuccessHandler) {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.authorizeExchange((authorize) -> authorize
|
||||||
|
.anyExchange()
|
||||||
|
.authenticated()
|
||||||
|
)
|
||||||
|
.oneTimeTokenLogin((ott) -> ott
|
||||||
|
.tokenGenerationSuccessHandler(ottSuccessHandler)
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
ServerGenerateOneTimeTokenRequestResolver resolver() {
|
||||||
|
return Mockito.spy(new DefaultServerGenerateOneTimeTokenRequestResolver());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
TestServerOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
|
||||||
|
return new TestServerOneTimeTokenGenerationSuccessHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static class TestServerOneTimeTokenGenerationSuccessHandler
|
private static class TestServerOneTimeTokenGenerationSuccessHandler
|
||||||
implements ServerOneTimeTokenGenerationSuccessHandler {
|
implements ServerOneTimeTokenGenerationSuccessHandler {
|
||||||
|
|
||||||
private static OneTimeToken lastToken;
|
private OneTimeToken lastToken;
|
||||||
|
|
||||||
private final ServerOneTimeTokenGenerationSuccessHandler delegate;
|
private final ServerOneTimeTokenGenerationSuccessHandler delegate;
|
||||||
|
|
||||||
@ -402,7 +491,7 @@ public class OneTimeTokenLoginSpecTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> handle(ServerWebExchange exchange, OneTimeToken oneTimeToken) {
|
public Mono<Void> handle(ServerWebExchange exchange, OneTimeToken oneTimeToken) {
|
||||||
lastToken = oneTimeToken;
|
this.lastToken = oneTimeToken;
|
||||||
return this.delegate.handle(exchange, oneTimeToken);
|
return this.delegate.handle(exchange, oneTimeToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,18 +16,17 @@
|
|||||||
|
|
||||||
package org.springframework.security.config.web.server
|
package org.springframework.security.config.web.server
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
import reactor.core.publisher.Mono
|
import org.mockito.ArgumentMatchers
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
import org.springframework.context.ApplicationContext
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
import org.springframework.context.annotation.Import
|
import org.springframework.context.annotation.Import
|
||||||
import org.springframework.context.ApplicationContext
|
|
||||||
import org.springframework.http.MediaType
|
import org.springframework.http.MediaType
|
||||||
import org.springframework.security.authentication.ott.GenerateOneTimeTokenRequest
|
|
||||||
import org.springframework.security.authentication.ott.OneTimeToken
|
import org.springframework.security.authentication.ott.OneTimeToken
|
||||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
|
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
|
||||||
import org.springframework.security.config.test.SpringTestContext
|
import org.springframework.security.config.test.SpringTestContext
|
||||||
@ -36,10 +35,10 @@ import org.springframework.security.core.userdetails.MapReactiveUserDetailsServi
|
|||||||
import org.springframework.security.core.userdetails.ReactiveUserDetailsService
|
import org.springframework.security.core.userdetails.ReactiveUserDetailsService
|
||||||
import org.springframework.security.core.userdetails.User
|
import org.springframework.security.core.userdetails.User
|
||||||
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers
|
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers
|
||||||
import org.springframework.security.web.server.authentication.ott.DefaultServerGenerateOneTimeTokenRequestResolver
|
|
||||||
import org.springframework.security.web.server.authentication.ott.ServerGenerateOneTimeTokenRequestResolver
|
|
||||||
import org.springframework.security.web.server.SecurityWebFilterChain
|
import org.springframework.security.web.server.SecurityWebFilterChain
|
||||||
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler
|
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler
|
||||||
|
import org.springframework.security.web.server.authentication.ott.DefaultServerGenerateOneTimeTokenRequestResolver
|
||||||
|
import org.springframework.security.web.server.authentication.ott.ServerGenerateOneTimeTokenRequestResolver
|
||||||
import org.springframework.security.web.server.authentication.ott.ServerOneTimeTokenGenerationSuccessHandler
|
import org.springframework.security.web.server.authentication.ott.ServerOneTimeTokenGenerationSuccessHandler
|
||||||
import org.springframework.security.web.server.authentication.ott.ServerRedirectOneTimeTokenGenerationSuccessHandler
|
import org.springframework.security.web.server.authentication.ott.ServerRedirectOneTimeTokenGenerationSuccessHandler
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient
|
import org.springframework.test.web.reactive.server.WebTestClient
|
||||||
@ -47,9 +46,7 @@ import org.springframework.web.reactive.config.EnableWebFlux
|
|||||||
import org.springframework.web.reactive.function.BodyInserters
|
import org.springframework.web.reactive.function.BodyInserters
|
||||||
import org.springframework.web.server.ServerWebExchange
|
import org.springframework.web.server.ServerWebExchange
|
||||||
import org.springframework.web.util.UriBuilder
|
import org.springframework.web.util.UriBuilder
|
||||||
import java.time.Duration
|
import reactor.core.publisher.Mono
|
||||||
import java.time.Instant
|
|
||||||
import java.time.ZoneOffset
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for [ServerOneTimeTokenLoginDsl]
|
* Tests for [ServerOneTimeTokenLoginDsl]
|
||||||
@ -102,7 +99,7 @@ class ServerOneTimeTokenLoginDslTests {
|
|||||||
.is3xxRedirection()
|
.is3xxRedirection()
|
||||||
.expectHeader().valueEquals("Location", "/login/ott")
|
.expectHeader().valueEquals("Location", "/login/ott")
|
||||||
|
|
||||||
val token = TestServerOneTimeTokenGenerationSuccessHandler.lastToken?.tokenValue
|
val token = lastToken()!!.tokenValue
|
||||||
|
|
||||||
client.mutateWith(SecurityMockServerConfigurers.csrf())
|
client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
.post()
|
.post()
|
||||||
@ -136,7 +133,7 @@ class ServerOneTimeTokenLoginDslTests {
|
|||||||
.is3xxRedirection()
|
.is3xxRedirection()
|
||||||
.expectHeader().valueEquals("Location", "/redirected")
|
.expectHeader().valueEquals("Location", "/redirected")
|
||||||
|
|
||||||
val token = TestServerOneTimeTokenGenerationSuccessHandler.lastToken?.tokenValue
|
val token = lastToken()!!.tokenValue
|
||||||
|
|
||||||
client.mutateWith(SecurityMockServerConfigurers.csrf())
|
client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
.post()
|
.post()
|
||||||
@ -154,8 +151,8 @@ class ServerOneTimeTokenLoginDslTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `oneTimeToken when custom token expiration time set then authenticate`() {
|
fun `oneTimeToken when custom request resolver set then custom resolver use`() {
|
||||||
spring.register(OneTimeTokenConfigWithCustomTokenExpirationTime::class.java).autowire()
|
spring.register(OneTimeTokenConfigWithCustomRequestResolver::class.java).autowire()
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
client.mutateWith(SecurityMockServerConfigurers.csrf())
|
client.mutateWith(SecurityMockServerConfigurers.csrf())
|
||||||
@ -171,29 +168,18 @@ class ServerOneTimeTokenLoginDslTests {
|
|||||||
.is3xxRedirection()
|
.is3xxRedirection()
|
||||||
.expectHeader().valueEquals("Location", "/login/ott")
|
.expectHeader().valueEquals("Location", "/login/ott")
|
||||||
|
|
||||||
client.mutateWith(SecurityMockServerConfigurers.csrf())
|
val resolver = spring.context
|
||||||
.post()
|
.getBean(ServerGenerateOneTimeTokenRequestResolver::class.java)
|
||||||
.uri{ uriBuilder:UriBuilder -> uriBuilder
|
|
||||||
.path("/ott/generate")
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
|
||||||
.body(BodyInserters.fromFormData("username", "user"))
|
|
||||||
.exchange()
|
|
||||||
.expectStatus()
|
|
||||||
.is3xxRedirection()
|
|
||||||
.expectHeader().valueEquals("Location", "/login/ott")
|
|
||||||
|
|
||||||
val token = TestServerOneTimeTokenGenerationSuccessHandler.lastToken
|
verify(resolver, Mockito.times(1))
|
||||||
|
.resolve(ArgumentMatchers.any(ServerWebExchange::class.java))
|
||||||
Assertions.assertThat(getCurrentMinutes(token!!.expiresAt)).isEqualTo(10)
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCurrentMinutes(expiresAt:Instant): Int {
|
private fun lastToken():OneTimeToken? =
|
||||||
val expiresMinutes = expiresAt.atZone(ZoneOffset.UTC).minute
|
spring.context.getBean(TestServerOneTimeTokenGenerationSuccessHandler::class.java)
|
||||||
val currentMinutes = Instant.now().atZone(ZoneOffset.UTC).minute
|
.lastToken
|
||||||
return expiresMinutes - currentMinutes
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebFlux
|
@EnableWebFlux
|
||||||
@ -202,18 +188,23 @@ class ServerOneTimeTokenLoginDslTests {
|
|||||||
open class OneTimeTokenConfig {
|
open class OneTimeTokenConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
open fun springWebFilterChain(http: ServerHttpSecurity,
|
||||||
|
ottSuccessHandler: ServerOneTimeTokenGenerationSuccessHandler): SecurityWebFilterChain {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http {
|
return http {
|
||||||
authorizeExchange {
|
authorizeExchange {
|
||||||
authorize(anyExchange, authenticated)
|
authorize(anyExchange, authenticated)
|
||||||
}
|
}
|
||||||
oneTimeTokenLogin {
|
oneTimeTokenLogin {
|
||||||
tokenGenerationSuccessHandler = TestServerOneTimeTokenGenerationSuccessHandler()
|
tokenGenerationSuccessHandler = ottSuccessHandler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
open fun ottSuccessHandler(): ServerOneTimeTokenGenerationSuccessHandler =
|
||||||
|
TestServerOneTimeTokenGenerationSuccessHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ -223,7 +214,8 @@ class ServerOneTimeTokenLoginDslTests {
|
|||||||
open class OneTimeTokenDifferentUrlsConfig {
|
open class OneTimeTokenDifferentUrlsConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
open fun springWebFilterChain(http: ServerHttpSecurity,
|
||||||
|
ottSuccessHandler: ServerOneTimeTokenGenerationSuccessHandler): SecurityWebFilterChain {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http {
|
return http {
|
||||||
authorizeExchange {
|
authorizeExchange {
|
||||||
@ -231,13 +223,17 @@ class ServerOneTimeTokenLoginDslTests {
|
|||||||
}
|
}
|
||||||
oneTimeTokenLogin {
|
oneTimeTokenLogin {
|
||||||
tokenGeneratingUrl = "/generateurl"
|
tokenGeneratingUrl = "/generateurl"
|
||||||
tokenGenerationSuccessHandler = TestServerOneTimeTokenGenerationSuccessHandler("/redirected")
|
tokenGenerationSuccessHandler = ottSuccessHandler
|
||||||
loginProcessingUrl = "/loginprocessingurl"
|
loginProcessingUrl = "/loginprocessingurl"
|
||||||
authenticationSuccessHandler = RedirectServerAuthenticationSuccessHandler("/authenticated")
|
authenticationSuccessHandler = RedirectServerAuthenticationSuccessHandler("/authenticated")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
open fun ottSuccessHandler(): ServerOneTimeTokenGenerationSuccessHandler =
|
||||||
|
TestServerOneTimeTokenGenerationSuccessHandler("/redirected")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ -252,36 +248,33 @@ class ServerOneTimeTokenLoginDslTests {
|
|||||||
@EnableWebFlux
|
@EnableWebFlux
|
||||||
@EnableWebFluxSecurity
|
@EnableWebFluxSecurity
|
||||||
@Import(OneTimeTokenLoginSpecTests.UserDetailsServiceConfig::class)
|
@Import(OneTimeTokenLoginSpecTests.UserDetailsServiceConfig::class)
|
||||||
open class OneTimeTokenConfigWithCustomTokenExpirationTime {
|
open class OneTimeTokenConfigWithCustomRequestResolver {
|
||||||
@Bean
|
@Bean
|
||||||
open fun securityWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
open fun securityWebFilterChain(http: ServerHttpSecurity,
|
||||||
|
ottSuccessHandler: ServerOneTimeTokenGenerationSuccessHandler): SecurityWebFilterChain {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return http {
|
return http {
|
||||||
authorizeExchange {
|
authorizeExchange {
|
||||||
authorize(anyExchange, authenticated)
|
authorize(anyExchange, authenticated)
|
||||||
}
|
}
|
||||||
oneTimeTokenLogin {
|
oneTimeTokenLogin {
|
||||||
tokenGenerationSuccessHandler = TestServerOneTimeTokenGenerationSuccessHandler()
|
tokenGenerationSuccessHandler = ottSuccessHandler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
open fun resolver(): ServerGenerateOneTimeTokenRequestResolver {
|
open fun resolver(): ServerGenerateOneTimeTokenRequestResolver =
|
||||||
val resolver = DefaultServerGenerateOneTimeTokenRequestResolver()
|
Mockito.spy(DefaultServerGenerateOneTimeTokenRequestResolver())
|
||||||
return ServerGenerateOneTimeTokenRequestResolver { exchange ->
|
|
||||||
resolver.resolve(exchange)
|
@Bean
|
||||||
.map { request -> GenerateOneTimeTokenRequest(request.username, Duration.ofSeconds(600)) }
|
open fun ottSuccessHandler(): ServerOneTimeTokenGenerationSuccessHandler =
|
||||||
}
|
TestServerOneTimeTokenGenerationSuccessHandler()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestServerOneTimeTokenGenerationSuccessHandler: ServerOneTimeTokenGenerationSuccessHandler {
|
private class TestServerOneTimeTokenGenerationSuccessHandler: ServerOneTimeTokenGenerationSuccessHandler {
|
||||||
private var delegate: ServerRedirectOneTimeTokenGenerationSuccessHandler? = null
|
private var delegate: ServerRedirectOneTimeTokenGenerationSuccessHandler? = null
|
||||||
|
var lastToken: OneTimeToken? = null
|
||||||
companion object {
|
|
||||||
var lastToken: OneTimeToken? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.delegate = ServerRedirectOneTimeTokenGenerationSuccessHandler("/login/ott")
|
this.delegate = ServerRedirectOneTimeTokenGenerationSuccessHandler("/login/ott")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user