Подтвердите номера телефонов в Интернете с помощью WebOTP API

Помогите пользователям с OTP, полученными через SMS.

Что такое WebOTP API?

Сегодня большинство людей в мире владеют мобильными устройствами, и разработчики обычно используют номера телефонов в качестве идентификаторов пользователей своих услуг.

Существует множество способов проверки номеров телефонов, но одним из наиболее распространенных является случайно сгенерированный одноразовый пароль (OTP), отправленный по SMS. Отправка этого кода обратно на сервер разработчика демонстрирует контроль над номером телефона.

Эта идея уже используется во многих сценариях для достижения:

  • Номер телефона как идентификатор пользователя. При подписке на новую услугу некоторые веб-сайты запрашивают номер телефона вместо адреса электронной почты и используют его в качестве идентификатора учетной записи.
  • Двухэтапная проверка. При входе в систему веб-сайт запрашивает одноразовый код, отправленный по SMS поверх пароля или другого фактора знания для дополнительной безопасности.
  • Подтверждение оплаты. Когда пользователь совершает платеж, запрос одноразового кода, отправленного через SMS, может помочь проверить намерения человека.

Текущий процесс создает трения для пользователей. Найти OTP в SMS-сообщении, а затем скопировать и вставить его в форму — затруднительное занятие, что снижает коэффициент конверсии на критически важных этапах взаимодействия с пользователем. Упростить эту задачу было давней просьбой к Интернету со стороны многих крупнейших мировых разработчиков. В Android есть API, который делает именно это . То же самое касается iOS и Safari .

API WebOTP позволяет вашему приложению получать сообщения особого формата, привязанные к домену вашего приложения. Благодаря этому вы можете программно получить OTP из SMS-сообщения и упростить проверку номера телефона пользователя.

Посмотрите это в действии

Допустим, пользователь хочет подтвердить свой номер телефона на веб-сайте. Веб-сайт отправляет пользователю текстовое сообщение через SMS, и пользователь вводит OTP из сообщения, чтобы подтвердить право собственности на номер телефона.

С API WebOTP эти шаги выполняются пользователем одним касанием, как показано в видео. Когда приходит текстовое сообщение, всплывает нижний лист и предлагается пользователю подтвердить свой номер телефона. После нажатия кнопки «Подтвердить» на нижнем листе браузер вставляет OTP в форму, и форма отправляется без необходимости нажатия пользователем кнопки «Продолжить» .

Весь процесс схематически изображен на изображении ниже.

Схема API WebOTP

Попробуйте демо-версию самостоятельно. Он не запрашивает ваш номер телефона и не отправляет SMS на ваше устройство, но вы можете отправить его с другого устройства, скопировав текст, отображаемый в демо-версии. Это работает, потому что при использовании WebOTP API не имеет значения, кто отправитель.

  1. Перейдите на https://web-otp.glitch.me в Chrome 84 или более поздней версии на устройстве Android.
  2. Отправьте на свой телефон следующее текстовое SMS-сообщение с другого телефона.
Your OTP is: 123456.

@web-otp.glitch.me #12345

Вы получили SMS и увидели приглашение ввести код в поле ввода? Именно так API WebOTP работает для пользователей.

Использование WebOTP API состоит из трех частей:

  • Правильно аннотированный тег <input>
  • JavaScript в вашем веб-приложении
  • Форматированный текст сообщения, отправленный через SMS.

Сначала я расскажу о теге <input> .

Аннотирование тега <input>

Сам WebOTP работает без каких-либо аннотаций HTML, но для совместимости с разными браузерами я настоятельно рекомендую вам добавить autocomplete="one-time-code" в тег <input> , где вы ожидаете, что пользователь введет OTP.

Это позволяет Safari 14 или более поздней версии предлагать пользователю автоматически заполнять поле <input> OTP при получении SMS в формате, описанном в разделе «Форматирование SMS-сообщения», даже если оно не поддерживает 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

Сам WebOTP API достаточно прост. Используйте navigator.credentials.get() для получения OTP. WebOTP добавляет к этому методу новую опцию otp . У него есть только одно свойство: transport , значение которого должно быть массивом со строкой 'sms' .

JavaScript

    …
    navigator.credentials.get({
      otp: { transport:['sms'] }
      …
    }).then(otp => {
    …

Это запускает поток разрешений браузера при поступлении SMS-сообщения. Если разрешение предоставлено, возвращаемое обещание разрешается с помощью объекта 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 => {
    …

Форматировать SMS-сообщение

Сам API должен выглядеть достаточно простым, но перед его использованием следует знать несколько вещей. Сообщение должно быть отправлено после вызова navigator.credentials.get() и должно быть получено на устройстве, на котором был вызван get() . Наконец, сообщение должно соответствовать следующему форматированию:

  • Сообщение начинается с (необязательного) удобочитаемого текста, содержащего буквенно-цифровую строку из четырех-десяти символов, по крайней мере, с одним числом, оставленным в последней строке для URL-адреса и одноразового пароля.
  • Доменной части URL-адреса веб-сайта, вызвавшего API, должен предшествовать @ .
  • URL-адрес должен содержать знак решетки (« # »), за которым следует OTP.

Например:

Your OTP is: 123456.

@www.example.com #123456

Вот плохие примеры:

Пример неправильного текста SMS Почему это не сработает
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. Имея общий формат для поддержки iframe из разных источников, WebOTP API доставляет OTP, привязанные к вложенным источникам. Например:

  • Пользователь посещает shop.example , чтобы купить пару обуви с помощью кредитной карты.
  • После ввода номера кредитной карты интегрированный поставщик платежей отображает форму из bank.example в iframe, предлагающую пользователю подтвердить свой номер телефона для быстрой оплаты.
  • bank.example отправляет пользователю SMS, содержащее OTP, чтобы он мог ввести его для подтверждения своей личности.

Чтобы использовать API WebOTP из iframe с перекрестным происхождением, вам нужно сделать две вещи:

  • Аннотируйте начало верхнего кадра и начало iframe в текстовом сообщении SMS.
  • Настройте политику разрешений, чтобы позволить iframe из разных источников получать OTP напрямую от пользователя.
WebOTP API внутри iframe в действии.

Вы можете попробовать демо-версию по адресу https://web-otp-iframe-demo.stackblitz.io .

Аннотировать привязанные источники к текстовому сообщению SMS

Когда WebOTP API вызывается из iframe, текстовое сообщение SMS должно включать источник верхнего кадра, которому предшествует @ , за которым следует 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>

См . дополнительные примеры указания политики разрешений .

Используйте WebOTP на рабочем столе

В Chrome WebOTP поддерживает прослушивание SMS-сообщений, полученных на других устройствах, чтобы помочь пользователям пройти проверку номера телефона на рабочем столе.

WebOTP API на рабочем столе.

Эта возможность требует, чтобы пользователь вошел в одну и ту же учетную запись Google как в настольном Chrome, так и в Android Chrome.

Все, что нужно сделать разработчикам, — это реализовать WebOTP API на своем веб-сайте для настольных компьютеров так же, как они это делают на своем мобильном веб-сайте, но никаких особых ухищрений не требуется.

Дополнительные сведения см. в разделе «Подтверждение номера телефона на рабочем столе с помощью WebOTP API» .

Часто задаваемые вопросы

Диалоговое окно не появляется, хотя я отправляю правильно отформатированное сообщение. Что происходит не так?

При тестировании API есть несколько предостережений:

  • Если номер телефона отправителя включен в список контактов получателя, этот API не будет активирован из-за конструкции базового API согласия пользователя SMS .
  • Если вы используете рабочий профиль на своем устройстве Android и WebOTP не работает, попробуйте вместо этого установить и использовать Chrome в своем личном профиле (т. е. в том же профиле, в котором вы получаете SMS-сообщения).

Проверьте формат и убедитесь, что ваше SMS-сообщение отформатировано правильно.

Совместим ли этот API между разными браузерами?

Chromium и WebKit договорились о формате текстовых сообщений SMS , и Apple объявила о его поддержке Safari, начиная с iOS 14 и macOS Big Sur. Хотя Safari не поддерживает API JavaScript WebOTP, путем аннотации элемента input с помощью autocomplete=["one-time-code"] клавиатура по умолчанию автоматически предлагает ввести OTP, если SMS-сообщение соответствует формату.

Безопасно ли использовать SMS для аутентификации?

Хотя SMS OTP полезен для проверки номера телефона при его первом вводе, проверку номера телефона с помощью SMS следует использовать с осторожностью для повторной аутентификации, поскольку номера телефонов могут быть перехвачены и переработаны операторами связи. WebOTP — это удобный механизм повторной аутентификации и восстановления, но сервисы должны сочетать его с дополнительными факторами, такими как проверка знаний, или использовать API веб-аутентификации для строгой аутентификации.

Где я могу сообщить об ошибках в реализации Chrome?

Вы нашли ошибку в реализации Chrome?

  • Сообщите об ошибке на crbug.com . Включите как можно больше деталей, простые инструкции по воспроизведению и установите для параметра «Компоненты» значение Blink>WebOTP .

Как я могу помочь этой функции?

Планируете ли вы использовать API WebOTP? Ваша публичная поддержка помогает нам расставлять приоритеты в функциях и показывает другим поставщикам браузеров, насколько важно их поддерживать. Отправьте твит @ChromiumDev, используя хэштег #WebOTP , и сообщите нам, где и как вы его используете.

Ресурсы