Обычно для подтверждения личности пользователя просят ввести одноразовый код, отправленный в SMS. Вот несколько примеров использования одноразовых кодов в SMS:
- Двухфакторная аутентификация. В дополнение к имени пользователя и паролю одноразовый код из SMS может использоваться как надежный сигнал того, что аккаунт принадлежит человеку, получившему этот код.
- Подтверждение номера телефона. В некоторых сервисах номер телефона используется в качестве основного идентификатора пользователя. В таких сервисах пользователи могут ввести свой номер телефона и одноразовый код, полученный в SMS, чтобы подтвердить свою личность. Иногда он сочетается с PIN-кодом, чтобы составить двухфакторную аутентификацию.
- Восстановление доступа к аккаунту. Когда пользователь теряет доступ к своему аккаунту, должен быть способ его восстановить. Отправка электронного письма на зарегистрированный адрес электронной почты или SMS-сообщения с одноразовым кодом на номер телефона — распространенные методы восстановления доступа к аккаунту.
- Подтверждение платежа. В платежных системах некоторые банки или эмитенты кредитных карт запрашивают дополнительную аутентификацию плательщика в целях безопасности. Для этого часто используется одноразовый код, отправляемый по SMS.
Ниже приведены рекомендации по созданию форм для одноразовых кодов в SMS для этих сценариев.
Контрольный список
Чтобы обеспечить максимальное удобство для пользователей при использовании SMS OTP, выполните следующие действия:
- Используйте элемент
<input>со следующими атрибутами:type="text"inputmode="numeric"autocomplete="one-time-code"
- Используйте
@BOUND_DOMAIN #OTP_CODEв качестве последней строки SMS с одноразовым кодом. - Используйте WebOTP API.
Используйте элемент <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 позволяет разработчикам указать, какое разрешение есть у браузера для автозаполнения, и сообщает браузеру, какой тип информации ожидается в поле.
Если у пользователя открыта форма и он получает SMS, операционная система autocomplete="one-time-code" эвристически анализирует одноразовый код в SMS и предлагает его для ввода. Он работает только в Safari 12 и более поздних версиях на iOS, iPadOS и macOS, но мы настоятельно рекомендуем его использовать, поскольку это лучший способ улучшить работу с одноразовыми кодами из SMS на этих платформах.
autocomplete="one-time-code" в действии.
autocomplete="one-time-code" улучшает взаимодействие с пользователем, но вы можете сделать больше, убедившись, что SMS-сообщение соответствует формату сообщения, привязанного к источнику.
Дополнительные атрибуты
Дополнительные атрибуты:
pattern– формат, которому должен соответствовать введенный одноразовый код. Используйте регулярные выражения, чтобы задать шаблон соответствия. Например,\d{6}ограничивает одноразовый код шестью цифрами. Подробнее оpatternчитайте в разделе Использование JavaScript для более сложной проверки в реальном времени.requiredуказывает, что поле обязательно для заполнения.
Дополнительные советы вы найдете в рекомендациях по созданию форм входа.
Форматирование текста SMS
Улучшите удобство ввода одноразового кода, используя спецификацию одноразовых кодов, связанных с источником и отправляемых по SMS.
В конце SMS-сообщения должен быть указан домен получателя, перед которым стоит символ @, и одноразовый код, перед которым стоит символ #.
Пример:
Your OTP is 123456
@web-otp.example.com #123456
Стандартный формат сообщений с одноразовыми кодами упрощает их извлечение и делает его более надежным. Связывание одноразовых кодов с сайтами усложняет обман пользователей с целью получения кода для вредоносных сайтов.
Точные правила форматирования
Вот точные правила:
- Сообщение начинается с (необязательного) человекочитаемого текста, который содержит буквенно-цифровую строку длиной от 4 до 10 символов, включающую хотя бы одну цифру. Последняя строка отводится под URL и одноразовый код.
- Перед доменной частью URL сайта, который вызвал API, должно быть указано
@. - URL должен содержать
#, за которым следует одноразовый код. Максимальное количество символов – 140.
У этого формата есть несколько преимуществ:
- Одноразовый код будет привязан к домену. Если пользователь находится на доменах, отличных от указанного в SMS-сообщении, предложение OTP не появится. Это также снижает риск фишинговых атак и потенциального взлома аккаунта.
- Теперь браузер сможет надежно извлекать одноразовый код, не полагаясь на загадочные и ненадежные эвристики.
Если сайт использует autocomplete="one-time-code", Safari в iOS 14 или более поздней версии предложит одноразовый код в соответствии с этими правилами.
Этот формат SMS-сообщений также подходит для других браузеров, кроме Safari. Браузеры Chrome, Opera и Vivaldi на Android также поддерживают правило одноразовых кодов, связанных с источником, с помощью WebOTP API, но не через autocomplete="one-time-code".
Как использовать WebOTP API
WebOTP API предоставляет доступ к одноразовому коду, полученному в SMS. Вызов navigator.credentials.get() с типом otp (OTPCredential), где transport включает sms, заставит сайт ждать SMS, соответствующего одноразовым кодам, привязанным к источнику, и предоставления доступа пользователем. После передачи одноразового кода в JavaScript сайт может использовать его в форме или отправить непосредственно на сервер.
navigator.credentials.get({
otp: {transport:['sms']}
})
.then(otp => input.value = otp.code);
Подробную информацию об использовании WebOTP API можно найти в статье Подтверждение номеров телефонов на сайтах с помощью WebOTP API. Вы также можете скопировать и вставить следующий фрагмент кода: Убедитесь, что в теге <form> заданы атрибуты action и method.
// 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);
});
});
}