Представляем подсказки, запросы связанного происхождения и сериализацию JSON для WebAuthn в Chrome.

В Chrome 128 и 129 представлены новые интересные функции WebAuthn — базового API для создания систем аутентификации на основе паролей.

  • Подсказки . Подсказки позволяют проверяющим сторонам (RP) лучше контролировать пользовательский интерфейс WebAuthn в браузере. Они особенно полезны для корпоративных пользователей, которые хотят использовать ключи безопасности.
  • Связанные запросы происхождения . С помощью связанных запросов происхождения RP могут сделать ключи доступа действительными на нескольких доменах. Если у вас есть несколько сайтов, теперь вы можете разрешить пользователям повторно использовать свои ключи доступа на всех ваших сайтах, устраняя трудности при входе в систему.
  • Сериализация JSON . API-интерфейсы сериализации JSON позволяют упростить внешний код RP за счет параметров кодирования и декодирования, а также учетных данных, передаваемых в API WebAuthn и из него.

Подсказки

С помощью hints проверяющие стороны (RP) теперь могут указывать предпочтения пользовательского интерфейса для создания ключа доступа или аутентификации с помощью ключа доступа.

Раньше, когда RP хотел ограничить аутентификатор, который пользователь может использовать для создания ключа доступа или для аутентификации, он мог authenticatorSelection.authenticatorAttachment , чтобы указать "platform" или "cross-platform" . Они соответственно ограничивают аутентификатор аутентификатором платформы или роуминговым аутентификатором . С помощью hints эта спецификация может быть более гибкой.

RP может использовать дополнительные hints в PublicKeyCredentialCreationOptions или PublicKeyCredentialRequestOptions чтобы указать "security-key" , "client-device" и "hybrid" в порядке предпочтения в массиве.

Ниже приведен пример запроса на создание учетных данных, в котором предпочтение отдается "cross-platform" аутентификаторам с подсказкой "security-key" . Это означает, что Chrome должен показывать пользовательский интерфейс, ориентированный на ключи безопасности, для корпоративных пользователей.

const credential = await navigator.credentials.create({
  publicKey: {
    challenge: *****,
    hints: ['security-key'],
    authenticatorSelection: {
      authenticatorAttachment: 'cross-platform'
    }
  }
});
Указав «ключ безопасности» в качестве подсказки, браузер отображает диалоговое окно, ориентированное на ключ безопасности.
Указав «ключ безопасности» в качестве подсказки, браузер отображает диалоговое окно, ориентированное на ключ безопасности.

Когда RP хочет определить приоритет сценария проверки между устройствами, он может отправить запрос аутентификации, в котором предпочтение отдается "cross-platform" аутентификаторам с "hybrid" в качестве подсказки.

const credential = await navigator.credentials.create({
  publicKey: {
    challenge: *****,
    residentKey: true,
    hints: ['hybrid']
    authenticatorSelection: {
      authenticatorAttachment: 'cross-platform'
    }
  }
});
Указав «гибрид» в качестве подсказки, браузер отображает диалоговое окно, ориентированное на вход на несколько устройств.
Указав «гибрид» в качестве подсказки, браузер отображает диалоговое окно, ориентированное на вход на несколько устройств.

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

Во всех запросах WebAuthn должен быть указан идентификатор проверяющей стороны (идентификатор RP), а все ключи доступа связаны с одним идентификатором RP. Традиционно источник мог указать идентификатор RP только на основе своего домена, поэтому в этом случае www.example.co.uk мог указать идентификатор RP example.co.uk , но не example.com . При использовании запросов связанного происхождения заявленный идентификатор RP можно проверить путем получения общеизвестного файла JSON, расположенного по адресу /.well-known/webauthn , из целевого домена. Таким образом, example.co.uk (а также example.in , example.de и т. д.) могут использовать идентификатор RP example.com , если example.com указывает их в следующем формате:

URL-адрес: https://example.com/.well-known/webauthn .

{
  "origins": [
    "https://example.co.uk",
    "https://example.de",
    "https://example.sg",
    "https://example.net",
    "https://exampledelivery.com",
    "https://exampledelivery.co.uk",
    "https://exampledelivery.de",
    "https://exampledelivery.sg",
    "https://myexamplerewards.com",
    "https://examplecars.com"
  ]
}

Узнайте, как настроить запросы связанного происхождения, в разделе «Разрешить повторное использование пароля на ваших сайтах с помощью запросов связанного происхождения» .

Сериализация JSON

Объекты запроса и ответа WebAuthn имеют несколько полей, которые содержат необработанные двоичные данные в ArrayBuffer, такие как идентификатор учетных данных, идентификатор пользователя или запрос. Если веб-сайт хочет использовать JSON для обмена этими данными со своим сервером, двоичные данные сначала необходимо закодировать, например, с помощью Base64URL. Это добавляет ненужную сложность для разработчиков, которые хотят начать использовать ключи доступа на своих веб-сайтах.

WebAuthn теперь предлагает API для анализа объектов запроса PublicKeyCredentialCreationOptions и PublicKeyCredentialRequestOptions WebAuthn непосредственно из JSON и сериализации ответа PublicKeyCredential непосредственно в JSON. Все поля со значениями ArrayBuffer, содержащие необработанные двоичные данные, автоматически преобразуются из или в значения, закодированные в Base64URL. Эти API доступны в Chrome 129.

Прежде чем создавать ключ доступа, получите объект PublicKeyCredentialCreationOptions в кодировке JSON с сервера и декодируйте его с помощью PublicKeyCredential.parseCreationOptionsFromJSON() .

Поддержка браузера

  • Хром: 129.
  • Край: 129.
  • Фаерфокс: 119.
  • Сафари: не поддерживается.

Источник

export async function registerCredential() {

  // Fetch encoded `PublicKeyCredentialCreationOptions`
  // and JSON decode it.
  const options = await fetch('/auth/registerRequest').json();

  // Decode `PublicKeyCredentialCreationOptions` JSON object
  const decodedOptions = PublicKeyCredential.parseCreationOptionsFromJSON(options);  

  // Invoke the WebAuthn create() function.
  const cred = await navigator.credentials.create({
    publicKey: decodedOptions,
  });
  ...

После создания ключа доступа закодируйте полученные учетные данные с помощью toJSON() , чтобы их можно было отправить на сервер.

Поддержка браузера

  • Хром: 129.
  • Край: 129.
  • Фаерфокс: 119.
  • Сафари: не поддерживается.

Источник

  ...
  const cred = await navigator.credentials.create({
    publicKey: options,
  });

  // Encode the credential to JSON and stringify
  const credential = JSON.stringify(cred.toJSON());

  // Send the encoded credential to the server
  await fetch('/auth/registerResponse', credential);
  ...

Перед аутентификацией с помощью ключа доступа получите PublicKeyRequestCreationOptions в кодировке JSON с сервера и декодируйте его с помощью PublicKeyCredential.parseRequestOptionsFromJSON() .

Поддержка браузера

  • Хром: 129.
  • Край: 129.
  • Фаерфокс: 119.
  • Сафари: не поддерживается.

Источник

export async function authenticate() {

  // Fetch encoded `PublicKeyCredentialRequestOptions`
  // and JSON decode it.
  const options = await fetch('/auth/signinRequest').json();

  // Decode `PublicKeyCredentialRequestOptions` JSON object
  const decodedOptions = PublicKeyCredential.parseRequestOptionsFromJSON(options);

  // Invoke the WebAuthn get() function.
  const cred = await navigator.credentials.get({
    publicKey: options
  });
  ...

После аутентификации с помощью ключа доступа закодируйте полученные учетные данные с помощью метода toJSON() , чтобы их можно было отправить на сервер.

Поддержка браузера

  • Хром: 129.
  • Край: 129.
  • Фаерфокс: 119.
  • Сафари: не поддерживается.

Источник

  ...
  const cred = await navigator.credentials.get({
    publicKey: options
  });

  // Encode the credential to JSON and stringify
  const credential = JSON.stringify(cred.toJSON());

  // Send the encoded credential to the server
  await fetch(`/auth/signinResponse`, credential);
  ...

Узнать больше

Чтобы узнать больше о WebAuthn и ключах доступа, посетите следующие ресурсы: