Improve Your Users’ 2FA Experience With HTML Attributes

Autocomplete, proper keyboards, and more

Phil Nash
Phil Nash
Feb 18, 2020 · 5 min read
Image for post
Image for post

There are plenty of opportunities for friction in the user experience when logging in, particularly while entering a two-factor authentication code. As developers, we should be building applications that support the need for account security but don’t detract from the user experience. Sometimes, it can feel as though these requirements are in a battle against each other.

In this piece, we’ll look at the humble <input> element and the HTML attributes that’ll help speed up our users' two-factor authentication experience.

The Default Experience

When you implement two-factor authentication for a web application, perhaps with the Authy two-factor authentication API, you’ll need a form for your user to input the one-time password you’re going to send them. You might create something similar to the following HTML:

<form action="/sessions/check-2fa" method="POST">
<div>
<label for="token">Please enter the code you were sent:</label>
<input type="text" name="token" id="token" />
</div>
<button type="submit">Check token</button>
</form>

This is a good experience already. The <input> has a name and a unique ID and the <label> is using the correct for attribute to explicitly associate with it, which is important for accessibility. You could also wrap the <label> around the <input> for the same effect. With a bit of CSS, this might look something like this:

Image for post
Image for post

However, we can progressively enhance this experience with just a few more attributes.

Getting the Right Keyboard

On mobiles or devices with on-screen keyboards, the first thing to notice is we’re presenting the full alpha keyboard. One time passwords are made of numerical characters, so it’d be much better to present the user with a number pad.

You might think that switching the type of <input> from "text" to "number" is the solution here:

<input type="number" name="token" id="token" />

You’d be wrong, though. This does trigger a different keyboard on iOS, but it still includes a number of useless keys.

Image for post
Image for post

Changing the type of field also changes the way the browser interprets that field. It could cause errors, too; if the two-factor authentication code starts with a zero, a number field may drop that leading zero.

inputmode

The inputmode attribute changes the keyboard the browser should display without changing the meaning of the data the field collects. We want our <input> to receive text input — but from the numeric keyboard. So instead, add inputmode="numeric"

<input type="text" name="token" id="token" inputmode="numeric" />

inputmode has a number of other values, including "tel" for telephone numbers, "email", "decimal", "url", "search", and "none", in case you want to render your own keyboard. This article on CSS tricks has all the details you need for the different inputmodes.

Browser support for inputmode is good for mobile operating systems these days, but a couple of years ago, it was in the wilderness. For older browsers, there’s another trick to trigger the numeric keyboard and include a bit of extra validation for free.

pattern

The pattern attribute allows you to validate the contents of an <input> using a regular expression. Using the pattern [0-9]* tells the browser we only accept numbers in the field and also triggers the number pad in browsers without inputmode support.

Our HTML looks like this now:

<input
type="text"
name="token"
id="token"
inputmode="numeric"
pattern="[0-9]*"
/>

And the keyboard is a much simpler numerical input:

Image for post
Image for post

One thing that’d make this form even easier to fill would be autocompletion of the one-time password.

HTML autocomplete

According to MDN, “Autocomplete lets web developers specify what if any permission the user agent has to provide automated assistance in filling out form field values, as well as guidance to the browser as to the type of information expected in the field.”

In iOS and Safari on macOS, we can take advantage of this to have the browser suggest two-factor authentication codes that are sent to the device over SMS. Adding the autocomplete attribute with the value "one-time-code" will trigger this behaviour.

<input
type="text"
name="token"
id="token"
inputmode="numeric"
pattern="[0-9]*"
autocomplete="one-time-code"
/>

With this, our <input> is complete, and the experience for the user now looks like this:

Image for post
Image for post

Other Useful Autocomplete Values

There are many autocomplete values available, covering everything from names and addresses to credit cards and other account details. For sign up and log in, there are a few autocomplete values that stand out as useful hints: username, email, new-password, and current-password.

Browsers and password managers have very good heuristics to find log-in forms on web pages, but using the username and current-password values make it very obvious. You definitely want to consider using these attributes if you’re building a log-in form with the username and password on different pages.

In a sign-up form, make sure to use the new-password value — as it triggers password suggestions in some browsers.

Image for post
Image for post

Autocompleting One-Time Passwords in Other Browsers

This autocomplete behaviour only exists in Safari on iOS and macOS, but the Chrome team is investigating similar ideas to streamline this process. There’s an experiment with an imperative SMS receiver API modelled on Android’s SMS receiver API. This would allow developers to extract the one-time password from the SMS and, because it’s in JavaScript, instantly submit the form, saving the user more time.

At the time of writing, this API is part of an origin trial that allows you to test it out and give feedback to the Chrome team. If this interests you, sign up and give the API a whirl.

Better Experiences Through HTML

In this piece, we’ve seen that with just a sprinkling of HTML attributes, we can improve the log-in experience for our users, particularly on mobile devices.

The <input> element is one of the most interesting HTML elements we have access to. Depending on the attributes, it can be a text field, a range slider, a file selector, a button, or many other options.

If you’re looking for an even better two-factor authentication experience, then take a look at Authy push authentications which cuts out the copying of codes entirely.
Thanks for reading!

Better Programming

Advice for programmers.

Sign up for The Best of Better Programming

By Better Programming

A weekly newsletter sent every Friday with the best articles we published that week. Code tutorials, advice, career opportunities, and more! Take a look

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Thanks to Zack Shapiro

Phil Nash

Written by

Phil Nash

Developer evangelist for Twilio. I write JavaScript and Ruby. Probably listening to ska punk right now.

Better Programming

Advice for programmers.

Phil Nash

Written by

Phil Nash

Developer evangelist for Twilio. I write JavaScript and Ruby. Probably listening to ska punk right now.

Better Programming

Advice for programmers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store