Подтверждайте номера телефонов в Интернете с помощью API WebOTP
Упростите для пользователей процедуру подтверждения телефона с помощью одноразовых паролей, полученных через СМС
Что такое API WebOTP? #
В наши дни большинство людей в мире владеют мобильными устройствами, и разработчики обычно используют телефонные номера для идентификации пользователей услуг.
Существует множество способов проверки телефонных номеров, но один из наиболее распространенных — случайный одноразовый пароль (OTP), отправленный по СМС. Отправка этого кода обратно на сервер разработчика подтверждает, что данный номер телефона контролируется пользователем.
Эта идея уже используется во многих сценариях:
- Номер телефона как идентификатор пользователя. При подписке на новую услугу некоторые веб-сайты запрашивают номер телефона вместо адреса электронной почты и используют его в качестве идентификатора учетной записи.
- Двухфакторная проверка. При входе в систему веб-сайт запрашивает одноразовый код, отправленный по СМС, в дополнение к паролю или другому фактору проверки в качестве дополнительной меры безопасности.
- Подтверждение об оплате. Запрос одноразового кода, отправленного по СМС при совершении платежа, помогает проверить намерение пользователя.
Текущий процесс неудобен пользователям, ведь нужно найти OTP в СМС-сообщениях, затем скопировать его и вставить в форму. Неудобство снижает конверсию на критически важных этапах пути потребителя. Многие крупнейшие мировые разработчики давно просили облегчить эту задачу. Для Android уже существует соответствующий API, как и для iOS и Safari.
API WebOTP позволяет приложению получать специальным образом форматированные сообщения, привязанные к домену приложения. Это делает возможным программное получение OTP из СМС и упрощает проверку номера телефона пользователя.
Практический пример #
Допустим, пользователь хочет подтвердить свой номер телефона на веб-сайте. Веб-сайт отправляет пользователю СМС-сообщение, и пользователь вводит OTP из сообщения, чтобы подтвердить принадлежность номера телефона.
С помощью API WebOTP эти действия выполняются легко, одним нажатием кнопки, как показано в видеоролике. Когда приходит текстовое сообщение, внизу появляется всплывающее окно, предлагающее пользователю подтвердить свой номер телефона. После нажатия кнопки Verify (Подтвердить) в нижнем окне браузер вставляет OTP в форму и происходит отправка, пользователю даже не нужно нажимать Continue (Продолжить).
endAside %}
Весь процесс показан на изображении ниже.
Запустите демонстрационный пример. Он не запрашивает номер телефона и не отправляет СМС на ваше устройство, но вы можете отправить СМС с другого устройства, скопировав текст, отображаемый в демонстрации. Это работает, потому что при использовании API WebOTP не имеет значения, кто отправитель.
- Перейдите на https://web-otp.glitch.me в Chrome 84 или более поздней версии на устройстве Android.
- Отправьте на свой телефон следующее СМС-сообщение с другого телефона.
Your OTP is: 123456.
@web-otp.glitch.me #12345
Получили ли вы СМС-сообщение и увидели ли подсказку о необходимости ввести код в поле ввода? Именно так работает API WebOTP для пользователей.
Использование WebOTP API состоит из трех частей:
- правильно аннотированный тег
<input>
; - JavaScript в вашем веб-приложении;
- форматированный текст СМС-сообщения.
Начнем с тега <input>
.
Аннотируйте тег <input>
#
Сам WebOTP работает без какой-либо HTML-аннотации, но для кросс-браузерной совместимости я настоятельно рекомендую добавить autocomplete="one-time-code"
в тег <input>
, в который пользователь должен ввести OTP.
Это дает возможность Safari 14 или более поздней версии браузера предлагать пользователю автоматически вставить OTP в поле <input>
при получении СМС в формате, описанном в разделе «Отформатируйте СМС-сообщение», даже если браузер не поддерживает WebOTP.
HTML
<form>
<input autocomplete="one-time-code" required/>
<input type="submit">
</form>
Используйте API WebOTP #
WebOTP несложный, поэтому просто скопируйте и вставьте следующий код. Далее я подробно объясню работу кода.
JavaScript
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);
});
});
}
Обнаружение функции #
Обнаружение функции происходит так же, как и для многих других API. Прослушиватель события DOMContentLoaded
будет ждать, когда дерево DOM будет готово к запросу.
JavaScript
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');
…
});
}
Обработайте OTP #
Сам API WebOTP достаточно прост. Используйте navigator.credentials.get()
для получения OTP. WebOTP добавляет к этому методу новый параметр otp
. У него есть только одно свойство: transport
, значением которого должен быть массив со строкой 'sms'
.
JavaScript
…
navigator.credentials.get({
otp: { transport:['sms'] }
…
}).then(otp => {
…
Это запускает поток разрешений браузера при получении СМС-сообщения. Если разрешение предоставлено, возвращаемое обещание разрешается с помощью объекта OTPCredential
.
Содержание полученного объекта OTPCredential
{
code: "123456" // Obtained OTP
type: "otp" // `type` is always "otp"
}
Затем передайте значение OTP в поле <input>
. Отправка формы напрямую устранит шаг, требующий от пользователя нажатия кнопки.
JavaScript
…
navigator.credentials.get({
otp: { transport:['sms'] }
…
}).then(otp => {
input.value = otp.code;
if (form) form.submit();
}).catch(err => {
console.error(err);
});
…
Прерывание сообщения #
В случае если пользователь вручную вводит OTP и отправляет форму, вы можете отменить вызов get()
, используя экземпляр AbortController
в объекте options
.
JavaScript
…
const ac = new AbortController();
…
if (form) {
form.addEventListener('submit', e => {
ac.abort();
});
}
…
navigator.credentials.get({
otp: { transport:['sms'] },
signal: ac.signal
}).then(otp => {
…
Отформатируйте СМС-сообщение #
Сам API выглядит простым, но есть несколько моментов, которые необходимо знать перед его использованием. Сообщение должно быть отправлено после вызова navigator.credentials.get()
и должно быть получено на устройстве, на котором была вызвана функция get()
. Наконец, сообщение должно соответствовать следующему формату:
- сообщение начинается с удобочитаемого текста (необязательно), который содержит буквенно-цифровую строку из 4–10 символов с как минимум одной цифрой, а в последней строке указываются URL-адрес и одноразовый пароль (OTP);
- символ
@
должен предшествовать доменной части URL-адреса веб-сайта, вызвавшего API; - URL-адрес должен содержать знак решетки ('
#
'), за которым следует OTP.
Например:
Your OTP is: 123456.
@www.example.com #123456
Вот плохие примеры:
Демонстрации #
Попробуйте различные сообщения с демонстрацией: https://web-otp.glitch.me
Вы также можете «форкнуть» пример и создать свою версию: https://glitch.com/edit/#!/web-otp.
Используйте WebOTP из iframe с перекрестным происхождением #
Ввод SMS OTP в iframe с перекрестным происхождением обычно используется для подтверждения платежа, особенно с использованием протокола 3D Secure. API WebOTP предоставляет OTP с привязкой к вложенным источникам, используя стандартный формат для поддержки iframes с перекрестным происхождением. Например:
- Пользователь заходит на сайт
shop.example
, чтобы купить пару обуви с помощью кредитной карты. - После ввода номера кредитной карты интегрированный поставщик платежей показывает форму из
bank.example
в окне iframe, предлагающую пользователю подтвердить свой номер телефона для быстрой оплаты. bank.example
отправляет СМС с OTP пользователю, чтобы он мог ввести OTP для подтверждения своей личности.
Чтобы использовать API WebOTP из iframe с перекрестным происхождением, нужно предпринять следующие два действия:
- аннотировать в СМС-сообщении источник iframe верхнего уровня и источник iframe;
- настроить политику разрешений, чтобы разрешить iframe с перекрестным происхождением напрямую получать OTP от пользователя.
Попробуйте демонстрацию на https://web-otp-iframe-demo.stackblitz.io.
Аннотируйте связанные источники (bound-origins) в текстовом СМС-сообщении #
Когда WebOTP API вызывается из iframe, СМС-сообщение в последней строке должно содержать источник iframe верхнего уровня (начинается с символа @
), затем OTP (начинается с символа #
) и источник iframe (начинается с символа @
).
Your verification code is 123456
@shop.example #123456 @bank.exmple
Настройте политику разрешений #
Чтобы использовать WebOTP в iframe с перекрестным происхождением, эмбеддер должен предоставить доступ к этому API через политику разрешений otp-credentials, чтобы избежать непреднамеренного поведения. В общем, есть два способа достичь этой цели:
через заголовок HTTP:
Permissions-Policy: otp-credentials=(self "https://bank.example")
через атрибут allow
тега iframe:
<iframe src="https://bank.example/…" allow="otp-credentials"></iframe>
См. другие примеры того, как указать политику разрешений.
Часто задаваемые вопросы #
Диалог не появляется, хотя я отправляю правильно отформатированное сообщение. Что не так? #
При тестировании API учтите следующие моменты:
- Если номер телефона отправителя включен в список контактов получателя, этот API не будет запускаться из-за конструкции базового API SMS User Consent.
- Если вы используете рабочий профиль на своем устройстве Android и WebOTP не работает, попробуйте вместо этого установить и использовать Chrome в своем личном профиле (т. е. в том же профиле, в котором вы получаете СМС).
Вернитесь к разделу о формате, чтобы проверить, правильно ли отформатировано ваше СМС.
Обладает ли этот API кросс-браузерной совместимостью? #
Chromium и WebKit согласовали формат текстовых СМС-сообщений, и Apple объявила о его поддержке в Safari, начиная с iOS 14 и macOS Big Sur. Хотя Safari не поддерживает API WebOTP JavaScript, аннотируя input
с помощью autocomplete=["one-time-code"]
, клавиатура по умолчанию автоматически предлагает ввести OTP, если СМС-сообщение соответствует формату.
Насколько безопасно использовать СМС для аутентификации? #
Хотя SMS OTP полезен для проверки номера телефона при его первом предоставлении, следует с осторожностью использовать проверку номера телефона через СМС для повторной аутентификации, поскольку телефонные номера могут быть перехвачены и повторно использованы операторами связи. WebOTP — удобный механизм повторной аутентификации и восстановления доступа, но службы должны сочетать его с дополнительными факторами, такими как аутентификация на основе знаний (KBA), или использовать API Web Authentication для надежной аутентификации.
Куда сообщать об ошибках в реализации Chrome? #
Вы нашли ошибку в реализации Chrome?
- Сообщите об ошибке на https://new.crbug.com. Укажите как можно больше подробностей, простые инструкции по воспроизведению и установите Components в значение
Blink>WebOTP
.
Чем я могу помочь с этой функцией? #
Планируете ли вы использовать API WebOTP? Ваша публичная поддержка поможет нам определить приоритетность функций и покажет другим производителям браузеров, насколько важно реализовать поддержку данных функций. Отправьте твит на @ChromiumDev с хештегом #WebOTP
и сообщите нам, где и как вы его используете.