Подтверждайте номера телефонов в Интернете с помощью API WebOTP
Упростите для пользователей процедуру подтверждения телефона с помощью одноразовых паролей, полученных через СМС
Published on • Updated on
Если вы хотите узнать больше о передовых методах использования форм SMS OTP, включая API WebOTP, прочитайте статью «Передовые методы использования форм SMS OTP».
Что такое API WebOTP?
В наши дни большинство людей в мире владеют мобильными устройствами, и разработчики обычно используют телефонные номера для идентификации пользователей услуг.
Существует множество способов проверки телефонных номеров, но один из наиболее распространенных — случайный одноразовый пароль (OTP), отправленный по СМС. Отправка этого кода обратно на сервер разработчика подтверждает, что данный номер телефона контролируется пользователем.
Эта идея уже используется во многих сценариях:
- Номер телефона как идентификатор пользователя. При подписке на новую услугу некоторые веб-сайты запрашивают номер телефона вместо адреса электронной почты и используют его в качестве идентификатора учетной записи.
- Двухфакторная проверка. При входе в систему веб-сайт запрашивает одноразовый код, отправленный по СМС, в дополнение к паролю или другому фактору проверки в качестве дополнительной меры безопасности.
- Подтверждение об оплате. Запрос одноразового кода, отправленного по СМС при совершении платежа, помогает проверить намерение пользователя.
Текущий процесс неудобен пользователям, ведь нужно найти OTP в СМС-сообщениях, затем скопировать его и вставить в форму. Неудобство снижает конверсию на критически важных этапах пути потребителя. Многие крупнейшие мировые разработчики давно просили облегчить эту задачу. Для Android уже существует соответствующий API, как и для iOS и Safari.
API WebOTP позволяет приложению получать специальным образом форматированные сообщения, привязанные к домену приложения. Это делает возможным программное получение OTP из СМС и упрощает проверку номера телефона пользователя.
Злоумышленники могут подделать СМС и перехватить номер телефона человека. Операторы также могут передавать телефонные номера новым пользователям после блокировки сим-карты. Хотя SMS OTP полезен для проверки номера телефона в описанных выше случаях, мы рекомендуем использовать дополнительные и более надежные формы аутентификации (например, многофакторную аутентификацию и Web Authentication API) для создания новых сессий для этих пользователей.
Практический пример
Допустим, пользователь хочет подтвердить свой номер телефона на веб-сайте. Веб-сайт отправляет пользователю СМС-сообщение, и пользователь вводит 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');
…
});
}
Для работы API WebOTP требуется безопасный источник (HTTPS). Обнаружение функции на веб-сайте с протоколом HTTP завершится ошибкой.
Обработайте 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
Вот плохие примеры:
Пример неправильно оформленного СМС | Почему это не сработает |
---|---|
Here is your code for @example.com #123456 | @ должен быть первым символом последней строки. |
Your code for @example.com is #123456 | @ должен быть первым символом последней строки. |
Your verification code is 123456 @example.com\t#123456 | Между @host и #code должен стоять одинарный пробел. |
Your verification code is 123456 @example.com #123456 | Между @host и #code должен стоять одинарный пробел. |
Your verification code is 123456 @ftp://example.com #123456 | Схема URL не должна включаться в сообщение. |
Your verification code is 123456 @https://example.com #123456 | Схема URL не должна включаться в сообщение. |
Your verification code is 123456 @example.com:8080 #123456 | Порт не должен включаться в сообщение. |
Your verification code is 123456 @example.com/foobar #123456 | Путь не должен включаться в сообщение. |
Your verification code is 123456 @example .com #123456 | В доменном имени не должно быть пробелов. |
Your verification code is 123456 @domain-forbiden-chars-#%/:<>?@[] #123456 | В доменном имени не должно быть запрещенных символов. |
@example.com #123456 Mambo Jumbo | @host и #code должны быть в последней строке. |
@example.com #123456 App hash #oudf08lkjsdf834 | @host и #code должны быть в последней строке. |
Your verification code is 123456 @example.com 123456 | Отсутствует # . |
Your verification code is 123456 example.com #123456 | Отсутствует @ . |
Hi mom, did you receive my last text | Отсутствуют @ и # . |
Демонстрации
Попробуйте различные сообщения с демонстрацией: 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>
См. другие примеры того, как указать политику разрешений.
На данный момент Chrome поддерживает вызовы API WebOTP только из iframe с перекрестным происхождением, которые имеют не более одного уникального источника в цепочке предков. В следующих сценариях:
a.com
->b.com
a.com
->b.com
->b.com
a.com
->a.com
->b.com
a.com
->b.com
->c.com
использование WebOTP на b.com
поддерживается, а на c.com
— нет.
Обратите внимание, что следующий сценарий также не поддерживается из-за отсутствия спроса и сложностей UX.
a.com
->b.com
->a.com
(вызывает API WebOTP)
Часто задаваемые вопросы
Диалог не появляется, хотя я отправляю правильно отформатированное сообщение. Что не так?
При тестировании 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
и сообщите нам, где и как вы его используете.
Больше вопросов можно найти в разделе часто задаваемых вопросов в поясняющей статье.
Updated on • Improve article