Merge branch '6.4.x'

TestOneTimeTokenGenerationSuccessHandler.lastToken to non-static variable

Closes gh-16472
This commit is contained in:
Rob Winch 2025-01-23 12:45:09 -06:00
commit f8132018d5
No known key found for this signature in database
2 changed files with 76 additions and 28 deletions

View File

@ -78,7 +78,7 @@ public class OneTimeTokenLoginConfigurerTests {
this.mvc.perform(post("/ott/generate").param("username", "user").with(csrf())) this.mvc.perform(post("/ott/generate").param("username", "user").with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/login/ott")); .andExpectAll(status().isFound(), redirectedUrl("/login/ott"));
String token = TestOneTimeTokenGenerationSuccessHandler.lastToken.getTokenValue(); String token = getLastToken().getTokenValue();
this.mvc.perform(post("/login/ott").param("token", token).with(csrf())) this.mvc.perform(post("/login/ott").param("token", token).with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/"), authenticated()); .andExpectAll(status().isFound(), redirectedUrl("/"), authenticated());
@ -90,7 +90,7 @@ public class OneTimeTokenLoginConfigurerTests {
this.mvc.perform(post("/generateurl").param("username", "user").with(csrf())) this.mvc.perform(post("/generateurl").param("username", "user").with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/redirected")); .andExpectAll(status().isFound(), redirectedUrl("/redirected"));
String token = TestOneTimeTokenGenerationSuccessHandler.lastToken.getTokenValue(); String token = getLastToken().getTokenValue();
this.mvc.perform(post("/loginprocessingurl").param("token", token).with(csrf())) this.mvc.perform(post("/loginprocessingurl").param("token", token).with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/authenticated"), authenticated()); .andExpectAll(status().isFound(), redirectedUrl("/authenticated"), authenticated());
@ -102,7 +102,7 @@ public class OneTimeTokenLoginConfigurerTests {
this.mvc.perform(post("/ott/generate").param("username", "user").with(csrf())) this.mvc.perform(post("/ott/generate").param("username", "user").with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/login/ott")); .andExpectAll(status().isFound(), redirectedUrl("/login/ott"));
String token = TestOneTimeTokenGenerationSuccessHandler.lastToken.getTokenValue(); String token = getLastToken().getTokenValue();
this.mvc.perform(post("/login/ott").param("token", token).with(csrf())) this.mvc.perform(post("/login/ott").param("token", token).with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/"), authenticated()); .andExpectAll(status().isFound(), redirectedUrl("/"), authenticated());
@ -206,7 +206,7 @@ public class OneTimeTokenLoginConfigurerTests {
this.mvc.perform(post("/ott/generate").param("username", "user").with(csrf())) this.mvc.perform(post("/ott/generate").param("username", "user").with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/login/ott")); .andExpectAll(status().isFound(), redirectedUrl("/login/ott"));
OneTimeToken token = TestOneTimeTokenGenerationSuccessHandler.lastToken; OneTimeToken token = getLastToken();
this.mvc.perform(post("/login/ott").param("token", token.getTokenValue()).with(csrf())) this.mvc.perform(post("/login/ott").param("token", token.getTokenValue()).with(csrf()))
.andExpectAll(status().isFound(), redirectedUrl("/"), authenticated()); .andExpectAll(status().isFound(), redirectedUrl("/"), authenticated());
@ -219,25 +219,37 @@ public class OneTimeTokenLoginConfigurerTests {
return expiresMinutes - currentMinutes; return expiresMinutes - currentMinutes;
} }
private OneTimeToken getLastToken() {
OneTimeToken lastToken = this.spring.getContext()
.getBean(TestOneTimeTokenGenerationSuccessHandler.class).lastToken;
return lastToken;
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EnableWebSecurity @EnableWebSecurity
@Import(UserDetailsServiceConfig.class) @Import(UserDetailsServiceConfig.class)
static class OneTimeTokenConfigWithCustomTokenExpirationTime { static class OneTimeTokenConfigWithCustomTokenExpirationTime {
@Bean @Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { SecurityFilterChain securityFilterChain(HttpSecurity http,
OneTimeTokenGenerationSuccessHandler ottSuccessHandler) throws Exception {
// @formatter:off // @formatter:off
http http
.authorizeHttpRequests((authz) -> authz .authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated() .anyRequest().authenticated()
) )
.oneTimeTokenLogin((ott) -> ott .oneTimeTokenLogin((ott) -> ott
.tokenGenerationSuccessHandler(new TestOneTimeTokenGenerationSuccessHandler()) .tokenGenerationSuccessHandler(ottSuccessHandler)
); );
// @formatter:on // @formatter:on
return http.build(); return http.build();
} }
@Bean
TestOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
return new TestOneTimeTokenGenerationSuccessHandler();
}
@Bean @Bean
GenerateOneTimeTokenRequestResolver generateOneTimeTokenRequestResolver() { GenerateOneTimeTokenRequestResolver generateOneTimeTokenRequestResolver() {
DefaultGenerateOneTimeTokenRequestResolver delegate = new DefaultGenerateOneTimeTokenRequestResolver(); DefaultGenerateOneTimeTokenRequestResolver delegate = new DefaultGenerateOneTimeTokenRequestResolver();
@ -255,19 +267,25 @@ public class OneTimeTokenLoginConfigurerTests {
static class OneTimeTokenDefaultConfig { static class OneTimeTokenDefaultConfig {
@Bean @Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { SecurityFilterChain securityFilterChain(HttpSecurity http,
OneTimeTokenGenerationSuccessHandler ottSuccessHandler) throws Exception {
// @formatter:off // @formatter:off
http http
.authorizeHttpRequests((authz) -> authz .authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated() .anyRequest().authenticated()
) )
.oneTimeTokenLogin((ott) -> ott .oneTimeTokenLogin((ott) -> ott
.tokenGenerationSuccessHandler(new TestOneTimeTokenGenerationSuccessHandler()) .tokenGenerationSuccessHandler(ottSuccessHandler)
); );
// @formatter:on // @formatter:on
return http.build(); return http.build();
} }
@Bean
TestOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
return new TestOneTimeTokenGenerationSuccessHandler();
}
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ -276,7 +294,8 @@ public class OneTimeTokenLoginConfigurerTests {
static class OneTimeTokenDifferentUrlsConfig { static class OneTimeTokenDifferentUrlsConfig {
@Bean @Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { SecurityFilterChain securityFilterChain(HttpSecurity http,
OneTimeTokenGenerationSuccessHandler ottSuccessHandler) throws Exception {
// @formatter:off // @formatter:off
http http
.authorizeHttpRequests((authz) -> authz .authorizeHttpRequests((authz) -> authz
@ -284,7 +303,7 @@ public class OneTimeTokenLoginConfigurerTests {
) )
.oneTimeTokenLogin((ott) -> ott .oneTimeTokenLogin((ott) -> ott
.tokenGeneratingUrl("/generateurl") .tokenGeneratingUrl("/generateurl")
.tokenGenerationSuccessHandler(new TestOneTimeTokenGenerationSuccessHandler("/redirected")) .tokenGenerationSuccessHandler(ottSuccessHandler)
.loginProcessingUrl("/loginprocessingurl") .loginProcessingUrl("/loginprocessingurl")
.authenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/authenticated")) .authenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/authenticated"))
); );
@ -292,6 +311,11 @@ public class OneTimeTokenLoginConfigurerTests {
return http.build(); return http.build();
} }
@Bean
TestOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
return new TestOneTimeTokenGenerationSuccessHandler("/redirected");
}
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ -300,7 +324,8 @@ public class OneTimeTokenLoginConfigurerTests {
static class OneTimeTokenFormLoginConfig { static class OneTimeTokenFormLoginConfig {
@Bean @Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { SecurityFilterChain securityFilterChain(HttpSecurity http,
OneTimeTokenGenerationSuccessHandler ottSuccessHandler) throws Exception {
// @formatter:off // @formatter:off
http http
.authorizeHttpRequests((authz) -> authz .authorizeHttpRequests((authz) -> authz
@ -308,12 +333,17 @@ public class OneTimeTokenLoginConfigurerTests {
) )
.formLogin(Customizer.withDefaults()) .formLogin(Customizer.withDefaults())
.oneTimeTokenLogin((ott) -> ott .oneTimeTokenLogin((ott) -> ott
.tokenGenerationSuccessHandler(new TestOneTimeTokenGenerationSuccessHandler()) .tokenGenerationSuccessHandler(ottSuccessHandler)
); );
// @formatter:on // @formatter:on
return http.build(); return http.build();
} }
@Bean
TestOneTimeTokenGenerationSuccessHandler ottSuccessHandler() {
return new TestOneTimeTokenGenerationSuccessHandler();
}
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ -337,7 +367,7 @@ public class OneTimeTokenLoginConfigurerTests {
static class TestOneTimeTokenGenerationSuccessHandler implements OneTimeTokenGenerationSuccessHandler { static class TestOneTimeTokenGenerationSuccessHandler implements OneTimeTokenGenerationSuccessHandler {
private static OneTimeToken lastToken; private OneTimeToken lastToken;
private final OneTimeTokenGenerationSuccessHandler delegate; private final OneTimeTokenGenerationSuccessHandler delegate;
@ -352,7 +382,7 @@ public class OneTimeTokenLoginConfigurerTests {
@Override @Override
public void handle(HttpServletRequest request, HttpServletResponse response, OneTimeToken oneTimeToken) public void handle(HttpServletRequest request, HttpServletResponse response, OneTimeToken oneTimeToken)
throws IOException, ServletException { throws IOException, ServletException {
lastToken = oneTimeToken; this.lastToken = oneTimeToken;
this.delegate.handle(request, response, oneTimeToken); this.delegate.handle(request, response, oneTimeToken);
} }

View File

@ -74,7 +74,7 @@ class OneTimeTokenLoginDslTests {
.redirectedUrl("/login/ott") .redirectedUrl("/login/ott")
) )
val token = TestOneTimeTokenGenerationSuccessHandler.lastToken?.tokenValue val token = getLastToken().tokenValue
this.mockMvc.perform( this.mockMvc.perform(
MockMvcRequestBuilders.post("/login/ott").param("token", token) MockMvcRequestBuilders.post("/login/ott").param("token", token)
@ -96,7 +96,7 @@ class OneTimeTokenLoginDslTests {
) )
.andExpectAll(MockMvcResultMatchers.status().isFound(), MockMvcResultMatchers.redirectedUrl("/redirected")) .andExpectAll(MockMvcResultMatchers.status().isFound(), MockMvcResultMatchers.redirectedUrl("/redirected"))
val token = TestOneTimeTokenGenerationSuccessHandler.lastToken?.tokenValue val token = getLastToken().tokenValue
this.mockMvc.perform( this.mockMvc.perform(
MockMvcRequestBuilders.post("/loginprocessingurl").param("token", token) MockMvcRequestBuilders.post("/loginprocessingurl").param("token", token)
@ -124,7 +124,7 @@ class OneTimeTokenLoginDslTests {
.redirectedUrl("/login/ott") .redirectedUrl("/login/ott")
) )
val token = TestOneTimeTokenGenerationSuccessHandler.lastToken val token = getLastToken()
assertThat(getCurrentMinutes(token!!.expiresAt)).isEqualTo(10) assertThat(getCurrentMinutes(token!!.expiresAt)).isEqualTo(10)
} }
@ -135,25 +135,36 @@ class OneTimeTokenLoginDslTests {
return expiresMinutes - currentMinutes return expiresMinutes - currentMinutes
} }
private fun getLastToken(): OneTimeToken {
val lastToken = spring.context
.getBean(TestOneTimeTokenGenerationSuccessHandler::class.java).lastToken
return lastToken!!
}
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@Import(UserDetailsServiceConfig::class) @Import(UserDetailsServiceConfig::class)
open class OneTimeTokenConfig { open class OneTimeTokenConfig {
@Bean @Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { open fun securityFilterChain(http: HttpSecurity, ottSuccessHandler: OneTimeTokenGenerationSuccessHandler): SecurityFilterChain {
// @formatter:off // @formatter:off
http { http {
authorizeHttpRequests { authorizeHttpRequests {
authorize(anyRequest, authenticated) authorize(anyRequest, authenticated)
} }
oneTimeTokenLogin { oneTimeTokenLogin {
oneTimeTokenGenerationSuccessHandler = TestOneTimeTokenGenerationSuccessHandler() oneTimeTokenGenerationSuccessHandler = ottSuccessHandler
} }
} }
// @formatter:on // @formatter:on
return http.build() return http.build()
} }
@Bean
open fun ottSuccessHandler(): TestOneTimeTokenGenerationSuccessHandler {
return TestOneTimeTokenGenerationSuccessHandler()
}
} }
@Configuration @Configuration
@ -162,14 +173,14 @@ class OneTimeTokenLoginDslTests {
open class OneTimeTokenConfigWithCustomTokenResolver { open class OneTimeTokenConfigWithCustomTokenResolver {
@Bean @Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { open fun securityFilterChain(http: HttpSecurity, ottSuccessHandler: OneTimeTokenGenerationSuccessHandler): SecurityFilterChain {
// @formatter:off // @formatter:off
http { http {
authorizeHttpRequests { authorizeHttpRequests {
authorize(anyRequest, authenticated) authorize(anyRequest, authenticated)
} }
oneTimeTokenLogin { oneTimeTokenLogin {
oneTimeTokenGenerationSuccessHandler = TestOneTimeTokenGenerationSuccessHandler() oneTimeTokenGenerationSuccessHandler = ottSuccessHandler
generateRequestResolver = DefaultGenerateOneTimeTokenRequestResolver().apply { generateRequestResolver = DefaultGenerateOneTimeTokenRequestResolver().apply {
this.setExpiresIn(Duration.ofMinutes(10)) this.setExpiresIn(Duration.ofMinutes(10))
} }
@ -179,6 +190,10 @@ class OneTimeTokenLoginDslTests {
return http.build() return http.build()
} }
@Bean
open fun ottSuccessHandler(): TestOneTimeTokenGenerationSuccessHandler {
return TestOneTimeTokenGenerationSuccessHandler()
}
} }
@ -187,7 +202,7 @@ class OneTimeTokenLoginDslTests {
@Import(UserDetailsServiceConfig::class) @Import(UserDetailsServiceConfig::class)
open class OneTimeTokenDifferentUrlsConfig { open class OneTimeTokenDifferentUrlsConfig {
@Bean @Bean
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { open fun securityFilterChain(http: HttpSecurity, ottSuccessHandler: OneTimeTokenGenerationSuccessHandler): SecurityFilterChain {
// @formatter:off // @formatter:off
http { http {
authorizeHttpRequests { authorizeHttpRequests {
@ -195,7 +210,7 @@ class OneTimeTokenLoginDslTests {
} }
oneTimeTokenLogin { oneTimeTokenLogin {
tokenGeneratingUrl = "/generateurl" tokenGeneratingUrl = "/generateurl"
oneTimeTokenGenerationSuccessHandler = TestOneTimeTokenGenerationSuccessHandler("/redirected") oneTimeTokenGenerationSuccessHandler = ottSuccessHandler
loginProcessingUrl = "/loginprocessingurl" loginProcessingUrl = "/loginprocessingurl"
authenticationSuccessHandler = SimpleUrlAuthenticationSuccessHandler("/authenticated") authenticationSuccessHandler = SimpleUrlAuthenticationSuccessHandler("/authenticated")
} }
@ -203,6 +218,11 @@ class OneTimeTokenLoginDslTests {
// @formatter:on // @formatter:on
return http.build() return http.build()
} }
@Bean
open fun ottSuccessHandler(): TestOneTimeTokenGenerationSuccessHandler {
return TestOneTimeTokenGenerationSuccessHandler("/redirected")
}
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ -213,9 +233,10 @@ class OneTimeTokenLoginDslTests {
InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin()) InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin())
} }
private class TestOneTimeTokenGenerationSuccessHandler : class TestOneTimeTokenGenerationSuccessHandler :
OneTimeTokenGenerationSuccessHandler { OneTimeTokenGenerationSuccessHandler {
private val delegate: OneTimeTokenGenerationSuccessHandler private val delegate: OneTimeTokenGenerationSuccessHandler
var lastToken: OneTimeToken? = null
constructor() { constructor() {
this.delegate = this.delegate =
@ -232,12 +253,9 @@ class OneTimeTokenLoginDslTests {
} }
override fun handle(request: HttpServletRequest, response: HttpServletResponse, oneTimeToken: OneTimeToken) { override fun handle(request: HttpServletRequest, response: HttpServletResponse, oneTimeToken: OneTimeToken) {
lastToken = oneTimeToken this.lastToken = oneTimeToken
delegate.handle(request, response, oneTimeToken) delegate.handle(request, response, oneTimeToken)
} }
companion object {
var lastToken: OneTimeToken? = null
}
} }
} }