DEV Community

Josue Jaramillo
Josue Jaramillo

Posted on

Simple Vanilla One-Time Password (OTP) module from scratch.

Hello people! As you can see in the title, this post is a guide about how to develop an OTP module. Why? Because it sounds easy but there are some things that we need to take into account when developing.

Initial HTML

To begin we will put together the basic structure of this, we will add our section, a title, a descriptive message and obviously our form with a single input to enter the code. Nothing difficult right? It should work.

<section class="auth-block container" aria-labelledby="auth-block-title-id">
      <h1 id="auth-block-title-id" class="auth-block__title">
        Enter your authentication code
      </h1>
      <p>
        We sent a message to your phone. Please add the code and click on
        continue
      </p>
      <form action="/check-code">
        <label for="auth-block-single-input-id">OTP Code:</label>
        <input id="auth-block-single-input-id" />
        <button type="reset">Clear</button>
        <button type="submit">Continue</button>
      </form>
    </section>
Enter fullscreen mode Exit fullscreen mode

And it works!

Image description

But... it can't be that simple, right? Well, no. There are certain things we need to consider when making an OTP input.

First of all these codes are usually numeric, so we should validate this. And as you can imagine, the easiest way would be to update the input to a type="number" input. But this will add some controls that don't make much sense when entering a code, I don't think someone will use the arrows until they get to their 6 digit number.

Image description

To avoid this, we will use a text input, but we will validate the type of text we expect, in this case, it is numeric. To do this we will take advantage of the pattern and add a simple regular expression.

pattern="[0-9]{6}"

Image description

But is it enough? Thanks to our pattern we can validate the length and prevent form submission, but from my point of view it would be better if the user can't enter letters, only numbers. So we'll add some JavaScript code :)

handleInput(e) {
    const { target } = e;
    target.value = target.value.replace(/[^0-9]/g, "");
  }
Enter fullscreen mode Exit fullscreen mode

This code takes advantage of a regular expression to replace anything that is not number with empty "". In this way, when the user tries to write text instead of numbers, it will be impossible.

Mobile

At this point we might think that we are done, if we try it on our computer it seems that everything is correct, but what if we try it on our phone? Don't you find it annoying that the full keyboard opens to enter numbers? We should only open the numeric keyboard. And we do that by adding an inputmode="numeric" to our input.

Image description

Why always iOS?

If you already have some experience developing sites and you care that they look good on all devices and browsers, you will know that on many occasions you have to make small changes for iOS. And this is not the exception LOL.

If you pay attention to the previous image, you will see a blank space right in the middle, this is where iOS has a cool feature that means that when you receive a message with an OTP code, it shows it directly as an autocomplete, so you don't you have to go to the messages app, copy the message, come back and paste it.

To achieve this we just need to add autocomplete="one-time-code" to the input.

Image description

And voila, we could continue adding styles, improving accessibility, make it required, etc.

But that will be for another post in which I'll explain how to make a more advanced OTP module like the one used by Epic Games and a lot of sites that has multiple inputs, one per number. However for now this code complies with the basic functionality that an input for OTP should have.

You can see the complete code example in the following link:

https://codesandbox.io/s/boring-neumann-0z3rki

Thanks for reading!

Top comments (0)