В 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'
}
}
});
![Указав «ключ безопасности» в качестве подсказки, браузер отображает диалоговое окно, ориентированное на ключ безопасности.](https://developer.chrome.com/static/blog/passkeys-updates-chrome-129/image/security-key.png?hl=ru)
Когда RP хочет определить приоритет сценария проверки между устройствами, он может отправить запрос аутентификации, в котором предпочтение отдается "cross-platform"
аутентификаторам с "hybrid"
в качестве подсказки.
const credential = await navigator.credentials.create({
publicKey: {
challenge: *****,
residentKey: true,
hints: ['hybrid']
authenticatorSelection: {
authenticatorAttachment: 'cross-platform'
}
}
});
![Указав «гибрид» в качестве подсказки, браузер отображает диалоговое окно, ориентированное на вход на несколько устройств.](https://developer.chrome.com/static/blog/passkeys-updates-chrome-129/image/cross-device.png?hl=ru)
Связанные запросы происхождения
С помощью запросов связанного происхождения 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()
.
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()
, чтобы их можно было отправить на сервер.
...
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()
.
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()
, чтобы их можно было отправить на сервер.
...
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 и ключах доступа, посетите следующие ресурсы: