Как мы создали вкладку Chrome DevTools WebAuthn

Фаваз Мохаммед
Fawaz Mohammad
Нина Сатраньо
Nina Satragno

API веб-аутентификации , также известный как WebAuthn , позволяет серверам использовать криптографию с открытым ключом, а не пароли, для регистрации и аутентификации пользователей. Это достигается за счет интеграции между этими серверами и надежными аутентификаторами. Эти аутентификаторы могут представлять собой специальные физические устройства (например, ключи безопасности) или интегрированные с платформами (например, считыватели отпечатков пальцев). Вы можете прочитать больше о WebAuthn здесь, на сайте webauthn.guide .

Болевые точки разработчика

До этого проекта в WebAuthn не было встроенной поддержки отладки в Chrome. Разработчику, создавшему приложение, использующее WebAuth, требовался доступ к физическим средствам аутентификации. Это было особенно сложно по двум причинам:

  1. Существует множество разновидностей аутентификаторов. Отладка широкого спектра конфигураций и возможностей потребовала, чтобы разработчик имел доступ к множеству различных, иногда дорогих средств аутентификации.

  2. Физические аутентификаторы по своей конструкции безопасны. Поэтому проверить их состояние обычно невозможно.

Мы хотели упростить эту задачу, добавив поддержку отладки прямо в Chrome DevTools.

Решение: новая вкладка WebAuthn

Вкладка WebAuthn DevTools значительно упрощает отладку WebAuthn, позволяя разработчикам эмулировать эти аутентификаторы, настраивать их возможности и проверять их состояния.

Новая вкладка WebAuthn

Выполнение

Добавление поддержки отладки в WebAuthn состояло из двух частей.

Двухэтапный процесс

Часть 1. Добавление домена WebAuthn в протокол Chrome DevTools

Во-первых, мы реализовали новый домен в протоколе Chrome DevTools (CDP) , который подключается к обработчику, взаимодействующему с серверной частью WebAuthn.

CDP соединяет интерфейс DevTools с Chromium. В нашем случае мы использовали доменные действия WebAuthn для моста между вкладкой WebAuthn DevTools и реализацией WebAuthn в Chromium.

Домен WebAuthn позволяет включать и отключать среду виртуального аутентификатора, которая отключает браузер от реального обнаружения аутентификатора и вместо этого подключает виртуальное обнаружение.

Мы также предоставляем методы в домене, которые действуют как тонкий слой для существующих интерфейсов Virtual Authenticator и Virtual Discovery, которые являются частью реализации Chromium WebAuthn. Эти методы включают добавление и удаление аутентификаторов, а также создание, получение и очистку их зарегистрированных учетных данных.

(Читать код )

Часть 2. Создание вкладки, ориентированной на пользователя

Во-вторых, мы создали вкладку для пользователя в интерфейсе DevTools . Вкладка состоит из вида и модели. Автоматически созданный агент соединяет домен с вкладкой.

Хотя необходимы три необходимых компонента, нам нужно было позаботиться только о двух из них: модели и представлении . Третий компонент — агент , генерируется автоматически после добавления домена. Вкратце, агент — это уровень, который передает вызовы между внешним интерфейсом и CDP.

Модель

Модель — это уровень JavaScript, который соединяет агента и представление. Для нашего случая модель достаточно проста. Он принимает команды из представления, формирует запросы так, чтобы их мог использовать CDP, а затем отправляет их через агента. Эти запросы обычно однонаправленные, без отправки информации обратно в представление.

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

(Читать код )

Вид

Новая вкладка WebAuthn

Мы используем представление, чтобы предоставить пользовательский интерфейс, который разработчик может найти при доступе к DevTools. Это содержит:

  1. Панель инструментов для включения среды виртуальной аутентификации.
  2. Раздел для добавления аутентификаторов.
  3. Раздел созданных аутентификаторов.

(Читать код )

Панель инструментов для включения среды виртуальной аутентификации

панель инструментов

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

Почему это необходимо? Важно, чтобы пользователь явно переключал среду, поскольку это отключает браузер от реального обнаружения аутентификатора. Таким образом, пока он включен, подключенные физические устройства аутентификации, такие как устройство считывания отпечатков пальцев, не будут распознаваться.

Мы решили, что явное переключение означает лучший пользовательский опыт, особенно для тех, кто заходит на вкладку WebAuthn, не ожидая, что реальное обнаружение будет отключено.

Добавление раздела Аутентификаторы

Добавление раздела Аутентификаторы

После включения среды виртуального аутентификатора мы предоставляем разработчику встроенную форму, которая позволяет ему добавить виртуальный аутентификатор. В этой форме мы предоставляем параметры настройки, которые позволяют пользователю выбрать протокол и методы транспортировки аутентификатора, а также поддерживать ли аутентификатор резидентные ключи и проверку пользователя.

Как только пользователь нажимает кнопку «Добавить» , эти параметры объединяются и отправляются в модель, которая вызывает создание аутентификатора. Как только это будет завершено, интерфейсная часть получит ответ, а затем изменит пользовательский интерфейс, включив в него вновь созданный аутентификатор.

Представление аутентификатора

Представление аутентификатора

Каждый раз, когда эмулируется аутентификатор, мы добавляем в представление аутентификатора раздел, представляющий его. Каждый раздел аутентификатора включает имя, идентификатор, параметры конфигурации, кнопки для удаления аутентификатора или включения его, а также таблицу учетных данных.

Имя аутентификатора

Имя аутентификатора настраивается и по умолчанию имеет значение «Аутентификатор», объединенное с последними 5 символами его идентификатора. Первоначально имя аутентификатора было его полным идентификатором и не могло быть изменено. Мы реализовали настраиваемые имена, чтобы пользователь мог маркировать аутентификатор в зависимости от его возможностей, физического аутентификатора, который он должен имитировать, или любого псевдонима, который немного легче понять, чем 36-значный идентификатор.

Таблица полномочий

Мы добавили таблицу в каждый раздел аутентификатора, в которой показаны все учетные данные, зарегистрированные аутентификатором. В каждой строке мы предоставляем информацию об учетных данных, а также кнопки для удаления или экспорта учетных данных.

В настоящее время мы собираем информацию для заполнения этих таблиц, опрашивая CDP, чтобы получить зарегистрированные учетные данные для каждого аутентификатора. В будущем мы планируем добавить событие для создания учетных данных.

Активная кнопка

Мы также добавили переключатель «Активно» в каждый раздел аутентификатора. Аутентификатор, который в данный момент активен, будет единственным, который прослушивает и регистрирует учетные данные. Без этого регистрация учетных данных с учетом нескольких аутентификаторов будет недетерминированной, что станет фатальной ошибкой при попытке протестировать WebAuthn с их использованием.

Мы реализовали активный статус с помощью метода SetUserPresence на виртуальных аутентификаторах. Метод SetUserPresence определяет, успешны ли тесты присутствия пользователя для данного аутентификатора. Если мы отключим его, аутентификатор не сможет прослушивать учетные данные. Таким образом, гарантируя, что он включен не более чем для одного аутентификатора (того, который установлен как активный), и отключив присутствие пользователя для всех остальных, мы можем добиться детерминированного поведения.

Интересная проблема, с которой мы столкнулись при добавлении активной кнопки, заключалась в том, чтобы избежать состояния гонки. Рассмотрим следующий сценарий:

  1. Пользователь нажимает переключатель «Активно» для аутентификатора X, отправляя запрос CDP на установку X как активного. Радиокнопка «Активно» для X выбрана, а все остальные отключены.

  2. Сразу после этого пользователь нажимает переключатель «Активно» для аутентификатора Y, отправляя запрос CDP, чтобы установить Y как активный. Радиокнопка «Активно» для Y выбрана, а все остальные, включая X, сняты с выбора.

  3. В серверной части вызов для установки Y как активного завершается и разрешается. Y теперь активен, а все остальные аутентификаторы — нет.

  4. В серверной части вызов для установки X как активного завершается и разрешается. X теперь активен, а все остальные аутентификаторы, включая Y, нет.

Теперь ситуация выглядит следующим образом: X является активным аутентификатором. Однако переключатель «Активно» для X не выбран. Y не является активным аутентификатором. Однако переключатель «Активно» для Y выбран . Существует разногласие между внешним интерфейсом и фактическим статусом аутентификаторов. Очевидно, это проблема.

Наше решение: установить псевдодвустороннюю связь между переключателями и активным аутентификатором. Во-первых, мы поддерживаем переменную activeId в представлении, чтобы отслеживать идентификатор текущего активного аутентификатора. Затем мы ждем вызова, чтобы активировать аутентификатор, чтобы вернуться, а затем устанавливаем activeId в идентификатор этого аутентификатора. Наконец, мы просматриваем каждый раздел аутентификатора. Если идентификатор этого раздела равен activeId , мы устанавливаем кнопку выбранной. В противном случае мы устанавливаем кнопку невыбранной.

Вот как это выглядит:


 async _setActiveAuthenticator(authenticatorId) {
   await this._clearActiveAuthenticator();
   await this._model.setAutomaticPresenceSimulation(authenticatorId, true);
   this._activeId = authenticatorId;
   this._updateActiveButtons();
 }
 
 _updateActiveButtons() {
   const authenticators = this._authenticatorsView.getElementsByClassName('authenticator-section');
   Array.from(authenticators).forEach(authenticator => {
     authenticator.querySelector('input.dt-radio-button').checked =
         authenticator.getAttribute('data-authenticator-id') === this._activeId;
   });
 }
 
 async _clearActiveAuthenticator() {
   if (this._activeId) {
     await this._model.setAutomaticPresenceSimulation(this._activeId, false);
   }
   this._activeId = null;
 }

Метрики использования

Мы хотели отслеживать использование этой функции. Изначально мы придумали два варианта.

  1. Подсчитайте каждый раз, когда открывалась вкладка WebAuthn в DevTools . Эта опция потенциально может привести к завышению подсчета, поскольку кто-то может открыть вкладку, фактически не используя ее.

  2. Отслеживайте, сколько раз на панели инструментов был установлен флажок «Включить виртуальную среду аутентификации» . У этой опции также была потенциальная проблема с чрезмерным подсчетом, поскольку некоторые из них могли включать и выключать среду несколько раз за один сеанс.

В конечном итоге мы решили пойти по второму пути, но ограничили подсчет, проверив, была ли среда уже включена в сеансе . Поэтому мы увеличим счетчик только на 1 независимо от того, сколько раз разработчик переключал среду. Это работает, поскольку каждый раз при повторном открытии вкладки создается новый сеанс, что сбрасывает проверку и позволяет снова увеличить метрику.

Краткое содержание

Спасибо за чтение! Если у вас есть предложения по улучшению вкладки WebAuthn, сообщите нам об этом, сообщив об ошибке .

Вот несколько ресурсов, если вы хотите узнать больше о WebAuthn:

Загрузите предварительный просмотр каналов

Рассмотрите возможность использования Chrome Canary , Dev или Beta в качестве браузера для разработки по умолчанию. Эти каналы предварительного просмотра дают вам доступ к новейшим функциям DevTools, тестируют передовые API-интерфейсы веб-платформы и находят проблемы на вашем сайте раньше, чем это сделают ваши пользователи!

Связь с командой Chrome DevTools

Используйте следующие параметры, чтобы обсудить новые функции и изменения в публикации или что-либо еще, связанное с DevTools.