You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -31,17 +31,19 @@ The One-Time Token Login works in two major steps.
31
31
1. User requests a token by submitting their user identifier, usually the username, and the token is delivered to them, often as a Magic Link, via e-mail, SMS, etc.
32
32
2. User submits the token to the one-time token login endpoint and, if valid, the user gets logged in.
33
33
34
-
[[default-pages]]
35
-
== Default Login Page and Default One-Time Token Submit Page
36
-
37
-
The `oneTimeTokenLogin()` DSL can be used in conjunction with `formLogin()`, which will produce an additional One-Time Token Request Form in the xref:servlet/authentication/passwords/form.adoc[default generated login page].
38
-
It will also set up the javadoc:org.springframework.security.web.authentication.ui.DefaultOneTimeTokenSubmitPageGeneratingFilter[] to generate a default One-Time Token submit page.
39
-
40
34
In the following sections we will explore how to configure OTT Login for your needs.
41
35
36
+
- <<default-pages,Understanding the integration with the default generated login page>>
42
37
- <<sending-token-to-user,Sending the token to the user>>
43
38
- <<changing-submit-page-url,Configuring the One-Time Token submit page>>
44
39
- <<changing-generate-url,Changing the One-Time Token generate URL>>
40
+
- <<customize-generate-consume-token,Customize how to generate and consume tokens>>
41
+
42
+
[[default-pages]]
43
+
== Default Login Page and Default One-Time Token Submit Page
44
+
45
+
The `oneTimeTokenLogin()` DSL can be used in conjunction with `formLogin()`, which will produce an additional One-Time Token Request Form in the xref:servlet/authentication/passwords/form.adoc[default generated login page].
46
+
It will also set up the javadoc:org.springframework.security.web.authentication.ui.DefaultOneTimeTokenSubmitPageGeneratingFilter[] to generate a default One-Time Token submit page.
45
47
46
48
[[sending-token-to-user]]
47
49
== Sending the Token to the User
@@ -63,7 +65,7 @@ Java::
63
65
public class SecurityConfig {
64
66
65
67
@Bean
66
-
public SecurityFilterChain filterChain(HttpSecurity http, MagicLinkGeneratedOneTimeTokenSuccessHandler magicLinkSender) {
68
+
public SecurityFilterChain filterChain(HttpSecurity http, MagicLinkGeneratedOneTimeTokenHandler magicLinkSender) {
public class MagicLinkGeneratedOneTimeTokenSuccessHandler implements GeneratedOneTimeTokenHandler {
82
+
public class MagicLinkGeneratedOneTimeTokenHandler implements GeneratedOneTimeTokenSuccessHandler {
81
83
82
84
private final MailSender mailSender;
83
85
@@ -177,7 +179,7 @@ class PageController {
177
179
----
178
180
======
179
181
180
-
<1> Make the `MagicLinkGeneratedOneTimeTokenSuccessHandler` a Spring bean
182
+
<1> Make the `MagicLinkGeneratedOneTimeTokenHandler` a Spring bean
181
183
<2> Create a login processing URL with the `token` as a query param
182
184
<3> Retrieve the user's email based on the username
183
185
<4> Use the `JavaMailSender` API to send the email to the user with the magic link
@@ -220,7 +222,7 @@ public class SecurityConfig {
220
222
}
221
223
222
224
@Component
223
-
public class MagicLinkGeneratedOneTimeTokenSuccessHandler implements GeneratedOneTimeTokenHandler {
225
+
public class MagicLinkGeneratedOneTimeTokenHandler implements GeneratedOneTimeTokenSuccessHandler {
224
226
// ...
225
227
}
226
228
----
@@ -284,7 +286,7 @@ public class SecurityConfig {
284
286
}
285
287
286
288
@Component
287
-
public class MagicLinkGeneratedOneTimeTokenSuccessHandler implements GeneratedOneTimeTokenSuccessHandler {
289
+
public class MagicLinkGeneratedOneTimeTokenHandler implements GeneratedOneTimeTokenSuccessHandler {
288
290
// ...
289
291
}
290
292
----
@@ -360,7 +362,7 @@ public class MyController {
360
362
}
361
363
362
364
@Component
363
-
public class MagicLinkGeneratedOneTimeTokenSuccessHandler implements GeneratedOneTimeTokenSuccessHandler {
365
+
public class MagicLinkGeneratedOneTimeTokenHandler implements GeneratedOneTimeTokenSuccessHandler {
364
366
// ...
365
367
}
366
368
----
@@ -405,4 +407,143 @@ class MagicLinkGeneratedOneTimeTokenSuccessHandler : GeneratedOneTimeTokenHandle
405
407
----
406
408
======
407
409
410
+
[[customize-generate-consume-token]]
411
+
== Customize How to Generate and Consume One-Time Tokens
412
+
413
+
The interface that define the common operations for generating and consuming one-time tokens is the javadoc:org.springframework.security.authentication.ott.OneTimeTokenService[].
414
+
Spring Security uses the javadoc:org.springframework.security.authentication.ott.InMemoryOneTimeTokenService[] as the default implementation of that interface, if none is provided.
415
+
416
+
Some of the most common reasons to customize the `OneTimeTokenService` are, but not limited to:
417
+
418
+
- Changing the one-time token expire time
419
+
- Storing more information from the generate token request
420
+
- Changing how the token value is created
421
+
- Additional validation when consuming a one-time token
408
422
423
+
There are two options to customize the `OneTimeTokenService`.
424
+
One option is to provide it as a bean, so it can be automatically be picked-up by the `oneTimeTokenLogin()` DSL:
425
+
426
+
.Passing the OneTimeTokenService as a Bean
427
+
[tabs]
428
+
======
429
+
Java::
430
+
+
431
+
[source,java,role="primary"]
432
+
----
433
+
@Configuration
434
+
@EnableWebSecurity
435
+
public class SecurityConfig {
436
+
437
+
@Bean
438
+
public SecurityFilterChain filterChain(HttpSecurity http) {
439
+
http
440
+
// ...
441
+
.formLogin(Customizer.withDefaults())
442
+
.oneTimeTokenLogin(Customizer.withDefaults());
443
+
return http.build();
444
+
}
445
+
446
+
@Bean
447
+
public OneTimeTokenService oneTimeTokenService() {
448
+
return new MyCustomOneTimeTokenService();
449
+
}
450
+
451
+
}
452
+
453
+
@Component
454
+
public class MagicLinkGeneratedOneTimeTokenHandler implements GeneratedOneTimeTokenSuccessHandler {
455
+
// ...
456
+
}
457
+
----
458
+
459
+
Kotlin::
460
+
+
461
+
[source,kotlin,role="secondary"]
462
+
----
463
+
@Configuration
464
+
@EnableWebSecurity
465
+
class SecurityConfig {
466
+
467
+
@Bean
468
+
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
469
+
http {
470
+
//...
471
+
formLogin { }
472
+
oneTimeTokenLogin { }
473
+
}
474
+
return http.build()
475
+
}
476
+
477
+
@Bean
478
+
open fun oneTimeTokenService(): OneTimeTokenService {
479
+
return MyCustomOneTimeTokenService()
480
+
}
481
+
}
482
+
483
+
@Component
484
+
class MagicLinkGeneratedOneTimeTokenSuccessHandler : GeneratedOneTimeTokenHandler {
485
+
// ...
486
+
}
487
+
----
488
+
======
489
+
490
+
The second option is to pass the `OneTimeTokenService` instance to the DSL, which is useful if there are multiple `SecurityFilterChain` and a different `OneTimeTokenService` is needed for each of them.
491
+
492
+
.Passing the OneTimeTokenService using the DSL
493
+
[tabs]
494
+
======
495
+
Java::
496
+
+
497
+
[source,java,role="primary"]
498
+
----
499
+
@Configuration
500
+
@EnableWebSecurity
501
+
public class SecurityConfig {
502
+
503
+
@Bean
504
+
public SecurityFilterChain filterChain(HttpSecurity http) {
0 commit comments