Verify phone numbers on the web with the WebOTP API
Auto Fill OTP Input using WebOTP API.
What is WebOTP API?
Nowadays, most of the company uses phone numbers to verify the user and here comes the use of WebOTP API. WebOTP API fetches the OTP from the SMS and inserts it in the input field.
The WebOTP API lets your app receive specially formatted messages bound to your app's domain. From this, you can programmatically obtain an OTP from an SMS message and verify a phone number for the user more easily. [From: web.dev].
Let's see how it's work in action
As displayed in the preview. First, the client receives the SMS then WebOTP API fetches the OTP with navigator.get() and add it into the input field as we instruct it.
Image from web.dev
You can also try the demo yourself.
Step 1: : Open web-otp.cb-ashik.me.
Step 2: : Send SMS to your phone (where you want to test) from another phone in the following format.
Your OTP is: 123456
@web-otp.cb-ashik.me #123456
Here the WebOTP API doesn't care about the first line, only the last line matters for it. It takes the number after the hash symbol(#) as OTP.
Did you receive the SMS and see the prompt to enter the code to the input area? That is how the WebOTP API works for users.
Now let's start creating own
Requirements
- Secure Origin (HTTPS)
- Latest chrome version
Using the WebOTP API consists of three things.
- A properly named
<input>
tag. Eg.<input autocomplete="one-time-password" />
- Javascript
- Formatted message text sent via SMS.
#. <input>
tag
<input>
tag in your web page must contain autocomplete="one-time-password"
attribute.
<form>
<input autocomplete="one-time-code" required />
<input type="submit" />
</form>
#. Javascript
We need to use javascript to use WebOTP API.
if ("OTPCredential" in window) {
window.addEventListener("DOMContentLoaded", (e) => {
const input = document.querySelector(
'input[autocomplete="one-time-code"]'
);
if (!input) return;
const ac = new AbortController();
const form = input.closest("form");
if (form) {
form.addEventListener("submit", (e) => {
ac.abort();
});
}
navigator.credentials
.get({
otp: { transport: ["sms"] },
signal: ac.signal,
})
.then((otp) => {
input.value = otp.code;
if (form) form.submit();
})
.catch((err) => {
console.log(err);
});
});
}
Let's separate the code. And see how it works.
Detecting the feature
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', e => {
const input = document.querySelector('input[autocomplete="one-time-code"]');
if (!input) return;
…
const form = input.closest('form');
…
});
}
Process OTP
…
navigator.credentials.get({
otp: { transport:['sms'] }
…
}).then(otp => {
…
Pass the value to <input>
.
…
navigator.credentials.get({
otp: { transport:['sms'] }
…
}).then(otp => {
input.value = otp.code;
if (form) form.submit();
}).catch(err => {
console.error(err);
});
…
Aborting the message
…
const ac = new AbortController();
…
if (form) {
form.addEventListener('submit', e => {
ac.abort();
});
}
…
navigator.credentials.get({
otp: { transport:['sms'] },
signal: ac.signal
}).then(otp => {
…
#. Format the message
- The message begins with (optional) human-readable text that contains a four to ten character alphanumeric string with at least one number leaving the last line for the URL and the OTP.
- The domain part of the URL of the website that invoked the API must be preceded by @.
- The URL must contain a pound sign ('#') followed by the OTP.
Your OTP is: 123456.
@example.com #123456
In my case:
Your OTP is: 123456.
@web-otp.cb-ashik.me #123456
Demo
Preview Link: https://web-otp.cb-ashik.me Github Link: https://github.com/projectashik/Verify-phone-numbers-on-the-web-with-the-WebOTP-API
Resources
https://developer.mozilla.org/en-US/docs/Web/API/WebOTP_API https://web.dev/web-otp/