> For the complete documentation index, see [llms.txt](https://wisdom.gitbook.io/gyan/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wisdom.gitbook.io/gyan/security/passwordless-login-with-spring-security-6/spring-security-onetimetoken.md).

# Spring Security OneTimeToken

Starting from Spring Security 6.4 it now supports One-Time Token (OTT) authentication via the `oneTimeTokenLogin()` DSL.

One-time token is a way where user can log in the system through EMAIL or SMS. They don't need to use a password to do it.

### How does It work?

* User enters his username/email and requests for one-time token.
* Spring security validates the user's existence, generates token and sends a one-time token login link to their corresponding email or phone number.
* The user receives the link and by clicking it, he redirects to the link, where he does login with the token provided.
* The system validates the token, do the authentication process and allows him to view the secured content.

### Classes involved in the token generation

### **`oneTimeTokenLogin()` dsl**

* It is a functional method that is used to configure one time token login in spring security.
* It takes **`OneTimeTokenLoginConfigurer`**  customizer as parameter.

### OneTimeTokenLoginConfigurer

* It's a configurer class that is used to configure one time token login dsl.
* &#x20;It provides default methods and configuration properties that are helpful in defining the one time token login configuration.
* Here are the classes and the properties defined-

{% code fullWidth="true" %}

```java
private OneTimeTokenService oneTimeTokenService = new InMemoryOneTimeTokenService();

private AuthenticationConverter authenticationConverter = new OneTimeTokenAuthenticationConverter();

private AuthenticationFailureHandler authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler();

private AuthenticationSuccessHandler authenticationSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();

private String defaultSubmitPageUrl = "/login/ott"; // default login page for ott, can be changed to custom one but need to handle csrf

private boolean submitPageEnabled = true; // enabled/disabled the submit page for ott

private String loginProcessingUrl = "/login/ott"; // url to process token, and gets called after varification

private String tokenGeneratingUrl = "/ott/generate"; // configured the ott token generator, in memory, jdbc

private OneTimeTokenGenerationSuccessHandler oneTimeTokenGenerationSuccessHandler = new RedirectOneTimeTokenGenerationSuccessHandler();

private AuthenticationProvider authenticationProvider = new OneTimeTokenAuthenticationProvider();
```

{% endcode %}

### GenerateOneTimeTokenFilter

* It's a filter that processes one-time token request with ant path matcher **/ott/generate.**&#x20;
* It has the **`OneTimeTokenService`** and **`OneTimeTokenGenerationSuccessHandler`**  configured that helps in filtering the request.
* It checks if request is for **/ott/generate** then validates the user and generates the one-time token and pass it to one time token success handler.

{% code fullWidth="true" %}

```java
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
       throws ServletException, IOException {
    if (!this.requestMatcher.matches(request)) {
       filterChain.doFilter(request, response);
       return;
    }
    String username = request.getParameter("username");
    if (!StringUtils.hasText(username)) {
       filterChain.doFilter(request, response);
       return;
    }
    GenerateOneTimeTokenRequest generateRequest = new GenerateOneTimeTokenRequest(username);
    OneTimeToken ott = this.tokenService.generate(generateRequest);
    this.tokenGenerationSuccessHandler.handle(request, response, ott);
}
```

{% endcode %}

### OneTimeTokenAuthenticationProvider

* It is an **`AuthenticationProvider (I)`** implementation class, responsible for authenticating users based on one-time tokens.
* It uses an **`OneTimeTokenService`** to consume tokens and an **`UserDetailsService`** to fetch user authorities.
* It is configured by default when we will use **`oneTimeTokenLogin()`** dsl.
* It has `public Authentication authenticate(Authentication authentication){}` method.
* This method authenticates the user, validates the token and generates a **`OneTimeTokenAuthenticationToken`** with user details.

{% code fullWidth="true" %}

```java
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    OneTimeTokenAuthenticationToken otpAuthenticationToken = (OneTimeTokenAuthenticationToken) authentication;
    OneTimeToken consumed = this.oneTimeTokenService.consume(otpAuthenticationToken);
    if (consumed == null) {
       throw new InvalidOneTimeTokenException("Invalid token");
    }
    UserDetails user = this.userDetailsService.loadUserByUsername(consumed.getUsername());
    OneTimeTokenAuthenticationToken authenticated = OneTimeTokenAuthenticationToken.authenticated(user,
          user.getAuthorities());
    authenticated.setDetails(otpAuthenticationToken.getDetails());
    return authenticated;
}
```

{% endcode %}

### DefaultLoginPageGeneratingFilter

* It is a filter responsible for generating the HTML pages for various login request.
* It generates templates for- login, token generation, token verification, ouath2 and passkeys.
* It generates the pages based on the flag passed in security config like formLogin().

### DefaultOneTimeTokenSubmitPageGeneratingFilter

* It is the filter that creates a default one-time token submit page.&#x20;
* If the request contains a token query parameter, then the page will automatically fill the form with the token value.
* It gets invoked on URL - **`/login/ott`  \[**&#x64;efault submit url]
* In the form it has the loggin processing url that url configured or to **`/login/ott [post]`**&#x20;
* It generates the page by capturing token from query path and gives continue button to user to login in the system.

### OneTimeTokenAuthenticationConverter

* It is an implementation of **AuthenticationConverter** that detects if the request contains a token parameter and constructs a **OneTimeTokenAuthenticationToken** with it.

<pre class="language-java"><code class="lang-java"><strong>public Authentication convert(HttpServletRequest request) {
</strong>    String token = request.getParameter("token");
    if (!StringUtils.hasText(token)) {
       this.logger.debug("No token found in request");
       return null;
    }
    return OneTimeTokenAuthenticationToken.unauthenticated(token);
}
</code></pre>

### SimpleUrlAuthenticationSuccessHandler

* It is an implementation class of **`AuthenticationSuccessHandler (I)`  .**
* It gets invoked upon successful authentication of the token and then redirects to the page configured.
* It checks for the URL that user configured and redirects to it.

### SimpleUrlAuthenticationFailureHandler

* It is an implementation class of **`AuthenticationFailureHandler (I)`  .**
* It gets invoked upon authentication failure when **`onAuthenticationFailure`** and then redirects to the URL configured by `defaultFailureUrl`
* It checks for the URL that user configured and redirects to it.

### OneTimeTokenService&#x20;

* It is an Interface for generating and consuming one-time tokens.

* It has implementation as -&#x20;

  * **InMemoryOneTimeTokenService -** Contains map of username and token.
  * **JdbcOneTimeTokenService** - Stores info in database.

* We can also implement our own one time token service.

* By default, it sets the expiry time as 5 minutes.

### OneTimeTokenGenerationSuccessHandler

* It is an interface that users need to implement and do the work after token generation.
* It has one method -&#x20;

  ```java
  public void handle(HttpServletRequest request, HttpServletResponse response, OneTimeToken oneTimeToken)
  ```
* Once the token generated successfully, this method will get invoked where the user can send the token via mail or SMS.
* After doing the process, the user can redirect to any success page that informs the user that the token got generated and delivered successfully.
