Улучшенная двухфакторная аутентификация с помощью WebOTP
Двухфакторная аутентификация (2FA) - отличный способ повысить безопасность учетных записей пользователей в приложении. Это помогает защитить от распространенных проблем с паролями, таких как выбор пользователями легко угадываемых паролей или повторное использование одного и того же пароля на нескольких сайтах. Существуют различные способы реализации двухфакторной аутентификации, включая SMS, с использованием приложения-аутентификатора и WebAuthn.
SMS является наиболее широко используемым и никуда не денется, поэтому мы, разработчики, должны сделать все возможное, чтобы создать лучший сервис SMS 2FA для наших пользователей. API WebOTP - это один из способов, которым мы можем помочь уменьшить трудности при входе в систему и даже обеспечить некоторую защиту от фишинга.
Что такое WebOTP API?
WebOTP API - это расширение к Credential Management API. Credential Management API начинался с предоставления нам возможности хранить учетные данные и получать к ним доступ в диспетчере паролей браузера, но теперь включает WebAuthn и двухфакторную аутентификацию. WebOTP API позволяет нам запрашивать у пользователя разрешение на считывание кода 2FA из входящего SMS-сообщения.
Когда вы внедряете WebOTP API, второй шаг процесса входа в систему может перейти от неудобного процесса чтения и копирования нескольких цифр из SMS-сообщения к нажатию одной кнопки. Большое улучшение, я думаю, вы согласитесь.
Чтобы внедрить Web OTP, вам нужно будет сделать две вещи:
- Обновите отправляемое сообщение в формате WebOTP
- Добавьте немного JavaScript на страницу входа, чтобы запросить разрешение на чтение сообщения
SMS-сообщение
Чтобы WebOTP API распознал сообщение как входящий код 2FA, вам нужно добавить строку в конец отправляемого вами сообщения. Эта строка должна содержать символ @
, за которым следует домен сайта, на который будет входить ваш пользователь, затем пробел, символ #
и затем сам код. Если ваш пользователь входит в систему на example.com
и код, который вы им отправляете, равен 123456
, тогда сообщение должно выглядеть следующим образом:
Ваш код для входа в приложение - 123456
@example.com #123456
Домен привязывает сообщение к веб-сайту, на который пользователь должен войти. Это помогает защитить от фишинга, WebOTP нельзя использовать для запроса кода из SMS, если домен, в который пользователь входит, не совпадает с доменом в сообщении. Очевидно, что это не может остановить пользователя, копирующего код напротив сообщения, но это может заставить их задуматься, если они ожидают такого поведения.
JavaScript
Как только вы настроите свои сообщения в нужном формате, вам понадобится некоторый JavaScript на вашей странице 2nd factor, который запустит WebOTP API, запросит у пользователя разрешение на доступ к сообщению и соберет код.
Самая минимальная версия этого кода выглядит следующим образом:
if ('OTPCredential' in window) {
navigator.credentials.get({
otp: {
transport: ['sms']
}
}).then((otp) => {
submitOTP(otp.code);
});
}
Мы просим объект navigator.credentials
получить одноразовый пароль (OTP) от передачи SMS. Если браузер обнаружит входящее сообщение с нужным доменом и кодом в нем, пользователю будет предложено запросить доступ. Если пользователь одобряет обещание, оно разрешается с помощью объекта otp
, который имеет свойство code
. Затем вы можете ввести этот код в форму и завершить процесс входа пользователя в систему.
Более полная версия кода, которая обрабатывает такие вещи, как поиск входных данных и формы, отмена запроса, если форма отправлена, и отправка формы, если запрос выполнен успешно, выглядит следующим образом:
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.error(err);
});
});
}
Это будет работать для многих сайтов, но копирование и вставка кода - не лучший способ поделиться кодом, поэтому придумаем что-то немного более простое.
Декларативный WebOTP с веб-компонентами
В Safari вы можете получить поведение, аналогичное поведению WebOTP API, добавив один атрибут к элементу <input>
для кода OTP. Установка autocomplete="one-time-code"
приведет к тому, что Safari предложит код из SMS через автозаполнение.
Вдохновленный этим, я хотел сделать WebOTP таким же простым. Итак, мы опубликовали веб-компонент, компонент <web-otp-input>, который обрабатывает весь процесс. Вы можете увидеть весь код и как его использовать на GitHub. Для краткого примера вы можете добавить компонент на свою страницу в качестве модуля ES:
<script type="module" src="https://unpkg.com/@philnash/web-otp-input"></script>
Или установите его в свой проект из npm:
npm install @philnash/web-otp-input
и импортируйте его в свое приложение:
import { WebOTPInput } from "@philnash/web-otp-input";
Затем вы можете обернуть <web-otp-input>
вокруг вашего существующего <input>
в <form>
, например:
<form action="/verification" method="POST">
<div>
<label for="otp">Enter your code:</label>
<web-otp-input>
<input type="text" autocomplete="one-time-code" inputmode="numeric" id="otp" name="otp" />
</web-otp-input>
</div>
<button type="submit">Submit</button>
</form>
Тогда работа с WebOTP будет происходить автоматически для любого пользователя в браузере, который его поддерживает, без написания какого-либо дополнительного JavaScript.
WebOTP: лучший опыт
WebOTP API делает двухфакторную аутентификацию с помощью SMS более удобной. Для браузеров, которые его поддерживают, ввод кода, который отправляется в качестве второго фактора, становится легким для пользователей.
Бывают даже случаи, когда это работает и для настольных браузеров. Для пользователя с Chrome на рабочем столе и Chrome на Android и вошедшего в свою учетную запись Google на обоих устройствах, вход на рабочем столе вызовет уведомление на мобильном устройстве с просьбой одобрить отправку кода на рабочий стол. Одобрив это на мобильных устройствах, вы передаете код в настольный браузер. Вам даже не нужно писать больше кода, чтобы справиться с этим, все, что вам нужно, - это JavaScript из этой статьи.
Если вы создаете двухфакторную аутентификацию или верификацию по телефону, рассмотрите возможность внедрения WebOTP API, чтобы упростить этот процесс для ваших пользователей.