Часто пользователи запрашивают одноразовый пароль (OTP) для подтверждения личности, отправляя SMS. Вот некоторые примеры использования SMS OTP:
- Двухфакторная аутентификация. Помимо имени пользователя и пароля, одноразовый пароль из SMS может быть использован в качестве убедительного подтверждения того, что учётная запись принадлежит человеку, получившему одноразовый пароль из SMS.
- Подтверждение номера телефона. Некоторые сервисы используют номер телефона в качестве основного идентификатора пользователя. В таких сервисах пользователи могут ввести свой номер телефона и одноразовый пароль из SMS для подтверждения личности. Иногда он комбинируется с PIN-кодом для двухфакторной аутентификации.
- Восстановление учётной записи. Если пользователь теряет доступ к своей учётной записи, необходимо найти способ её восстановить. Отправка электронного письма на зарегистрированный адрес электронной почты или SMS с одноразовым паролем на номер телефона — распространённые способы восстановления учётной записи.
- Подтверждение платежа. В платёжных системах некоторые банки или эмитенты кредитных карт требуют от плательщика дополнительную аутентификацию в целях безопасности. Для этой цели обычно используется одноразовый пароль SMS.
Продолжайте читать, чтобы ознакомиться с передовыми методами создания форм одноразовых SMS-паролей для этих случаев использования.
Контрольный список
Чтобы обеспечить наилучший пользовательский опыт использования SMS-одноразового пароля, выполните следующие действия:
- Используйте элемент
<input>
с:-
type="text"
-
inputmode="numeric"
-
autocomplete="one-time-code"
-
- Используйте
@BOUND_DOMAIN #OTP_CODE
в качестве последней строки SMS-сообщения OTP. - Используйте API WebOTP .
Используйте элемент <input>
Использование формы с элементом <input>
— важнейший совет, которому стоит следовать, поскольку он работает во всех браузерах. Даже если другие советы из этой статьи не работают в каком-либо браузере, пользователь всё равно сможет ввести и отправить одноразовый пароль вручную.
<form action="/verify-otp" method="POST">
<input type="text"
inputmode="numeric"
autocomplete="one-time-code"
pattern="\d{6}"
required>
</form>
Ниже приведено несколько идей, которые позволят максимально эффективно использовать функциональность браузера при вводе данных.
type="text"
Поскольку одноразовые пароли обычно состоят из пяти- или шестизначных чисел, использование type="number"
для поля ввода может показаться интуитивно понятным, поскольку при этом мобильная клавиатура переключается на ввод только цифр. Это не рекомендуется, поскольку браузер ожидает, что поле ввода будет содержать исчисляемое число, а не последовательность нескольких чисел, что может привести к непредсказуемому поведению. Использование type="number"
приводит к отображению кнопок «вверх» и «вниз» рядом с полем ввода; нажатие этих кнопок увеличивает или уменьшает число и может удалить предшествующие нули.
Вместо этого используйте type="text"
. Это не превратит мобильную клавиатуру в набор только цифр, но это нормально, поскольку следующий совет по использованию inputmode="numeric"
решает эту задачу.
inputmode="numeric"
Используйте inputmode="numeric"
, чтобы переключить мобильную клавиатуру только на цифры.
Некоторые веб-сайты используют type="tel"
для полей ввода одноразовых паролей, поскольку при фокусировке на мобильном устройстве он также переключает клавиатуру в режим отображения только цифр (включая *
и #
). Этот хак использовался ранее, когда inputmode="numeric"
не был широко поддержан. С тех пор, как Firefox начал поддерживать inputmode="numeric"
, нет необходимости использовать семантически некорректный хак type="tel"
.
autocomplete="one-time-code"
Атрибут autocomplete
позволяет разработчикам указывать, какое разрешение имеет браузер для предоставления помощи при автозаполнении, и информирует браузер о типе информации, ожидаемой в поле.
При использовании autocomplete="one-time-code"
при получении пользователем SMS-сообщения при открытой форме операционная система эвристически анализирует одноразовый пароль в SMS-сообщении, и клавиатура предлагает пользователю ввести одноразовый пароль. Функция работает только в Safari 12 и более поздних версиях на iOS, iPadOS и macOS, но мы настоятельно рекомендуем использовать её, поскольку это лучший способ улучшить работу с одноразовыми паролем в SMS на этих платформах.
autocomplete="one-time-code"
в действии. autocomplete="one-time-code"
улучшает пользовательский интерфейс, но вы можете сделать больше , убедившись, что SMS-сообщение соответствует исходному формату сообщения .
Необязательные атрибуты
Дополнительные атрибуты включают в себя:
-
pattern
определяет формат, которому должен соответствовать введённый одноразовый пароль. Используйте регулярные выражения для задания шаблона соответствия. Например,\d{6}
ограничивает одноразовый пароль шестизначной строкой. Подробнее оpattern
читайте в статье «Использование JavaScript для более сложной проверки в режиме реального времени» . -
required
указывает, что пользователь должен заполнить поле.
Для получения дополнительных рекомендаций ознакомьтесь с нашими рекомендациями по заполнению формы входа .
Форматировать текст СМС
Улучшите пользовательский опыт ввода одноразовых паролей, приведя их в соответствие со спецификацией одноразовых кодов, привязанных к месту отправки и отправляемых по SMS .
По сути, правило форматирования выглядит следующим образом: завершите SMS-сообщение указанием домена получателя, предваряемого символом @
, и одноразовым паролем, предваряемым символом #
.
Например:
Your OTP is 123456
@web-otp.glitch.me #123456
Стандартный формат одноразовых паролей (OTP) упрощает извлечение и повышает надёжность. Связывание одноразовых паролей с веб-сайтами затрудняет попытки обманным путём заставить пользователей предоставить код вредоносным сайтам.
Точные правила форматирования
Точные правила таковы:
- Сообщение начинается с (необязательного) удобочитаемого текста, который содержит строку из четырех-десяти букв и цифр, содержащую как минимум одну цифру, а последняя строка предназначена для URL-адреса и одноразового пароля.
- Доменная часть URL-адреса веб-сайта, вызвавшего API, должна предваряться символом
@
. - URL-адрес должен содержать символ
#
, за которым следует одноразовый пароль. Количество символов должно быть не более 140.
Использование этого формата дает несколько преимуществ:
- Одноразовый пароль будет привязан к домену. Если пользователь находится в доменах, отличных от указанного в SMS-сообщении, предложение одноразового пароля не появится. Это также снижает риск фишинговых атак и потенциального взлома аккаунта.
- Теперь браузер сможет надежно извлекать одноразовые пароли, не полагаясь на загадочные и ненадежные эвристики.
Если веб-сайт использует autocomplete="one-time-code"
, Safari с iOS 14 или более поздней версией предложит одноразовый пароль в соответствии со следующими правилами.
Этот формат SMS-сообщений поддерживается и другими браузерами, помимо Safari. Chrome, Opera и Vivaldi на Android также поддерживают правило одноразовых кодов с привязкой к источнику через API WebOTP, хотя и не через autocomplete="one-time-code"
.
Используйте API WebOTP
API WebOTP предоставляет доступ к одноразовому паролю, полученному в SMS-сообщении. Вызывая метод navigator.credentials.get()
с типом otp
( OTPCredential
), где transport
включает sms
, веб-сайт ожидает доставки SMS-сообщения, соответствующего одноразовым кодам, привязанным к источнику, и предоставления пользователю доступа. После передачи одноразового пароля в JavaScript веб-сайт может использовать его в форме или отправить непосредственно на сервер методом POST.
navigator.credentials.get({
otp: {transport:['sms']}
})
.then(otp => input.value = otp.code);
Подробно о том, как использовать API WebOTP, читайте в статье «Проверка телефонных номеров в интернете с помощью API WebOTP» или скопируйте и вставьте следующий фрагмент кода. Обязательно задайте атрибуты action
и method
в форме <form>
.
// Feature detection
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', e => {
const input = document.querySelector('input[autocomplete="one-time-code"]');
if (!input) return;
// Cancel the WebOTP API if the form is submitted manually.
const ac = new AbortController();
const form = input.closest('form');
if (form) {
form.addEventListener('submit', e => {
// Cancel the WebOTP API.
ac.abort();
});
}
// Invoke the WebOTP API
navigator.credentials.get({
otp: { transport:['sms'] },
signal: ac.signal
}).then(otp => {
input.value = otp.code;
// Automatically submit the form when an OTP is obtained.
if (form) form.submit();
}).catch(err => {
console.log(err);
});
});
}