mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-22 20:12:14 +00:00
Merge branch '6.4.x'
TestOneTimeTokenGenerationSuccessHandler.lastToken to non-static variable Closes gh-16472
This commit is contained in:
commit
f8132018d5
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user