Начиная с Chrome 126, разработчики могут начать использовать исходную пробную версию пакета функций Federated Credential Management API (FedCM) для настольных компьютеров, которые позволяют использовать некоторые варианты использования авторизации . Пакет состоит из API-интерфейса продолжения и API-интерфейса параметров, которые обеспечивают процесс авторизации OAuth, аналогичный потоку авторизации, с использованием диалогового окна разрешений, предоставленного поставщиком удостоверений (IdP). Пакет также включает в себя другие изменения, такие как API полей, несколько URL-адресов configURL и пользовательские метки учетной записи. Начиная с Chrome 126, мы также представляем исходную пробную версию API доступа к хранилищу (SAA), которая автоматически разрешает запросы SAA, если пользователь ранее успешно входил в систему с помощью FedCM.
Пробная версия Origin: пакет API продолжения FedCM
Пакет FedCM Continuation API состоит из нескольких расширений FedCM:
Продолжение API
Вы можете посмотреть демо-версию API на Glitch .
API продолжения позволяет конечной точке утверждения идентификатора IdP при необходимости возвращать URL-адрес, который FedCM отобразит, чтобы позволить пользователю продолжить многоэтапный процесс входа. Это позволяет IdP запросить у пользователя предоставить проверяющей стороне (RP) разрешения, выходящие за рамки существующих возможностей пользовательского интерфейса FedCM, например, доступ к ресурсам на стороне сервера пользователя.
Обычно конечная точка утверждения идентификатора возвращает токен, необходимый для аутентификации.
{
"token": "***********"
}
Однако с помощью Continuation API конечная точка утверждения идентификатора может возвращать свойство continue_on
, которое включает в себя абсолютный или относительный путь к конечной точке утверждения идентификатора.
{
// In the id_assertion_endpoint, instead of returning a typical
// "token" response, the IdP decides that it needs the user to
// continue on a pop-up window:
"continue_on": "/oauth/authorize?scope=..."
}
Как только браузер получает ответ continue_on
, открывается новое всплывающее окно, которое направляет пользователя по указанному пути.
После того, как пользователь взаимодействует со страницей, например, предоставляя дополнительное разрешение на обмен дополнительной информацией с RP, страница IdP может вызвать IdentityProvider.resolve()
, чтобы разрешить исходный вызов navigator.credentials.get()
и вернуть токен в качестве аргумента. .
document.getElementById('allow_btn').addEventListener('click', async () => {
let accessToken = await fetch('/generate_access_token.cgi');
// Closes the window and resolves the promise (that is still hanging
// in the relying party's renderer) with the value that is passed.
IdentityProvider.resolve(accessToken);
});
Затем браузер сам закроет всплывающее окно и вернет токен вызывающему API.
Если пользователь отклоняет запрос, вы можете закрыть окно, вызвав IdentityProvider.close()
.
IdentityProvider.close();
Если по какой-то причине пользователь изменил свою учетную запись во всплывающем окне (например, IdP предлагает функцию «переключить пользователя» или в случаях делегирования), вызов разрешения принимает необязательный второй аргумент, позволяющий что-то вроде:
IdentityProvider.resolve(token, {accountId: '1234');
API параметров
API параметров позволяет RP предоставлять дополнительные параметры конечной точке утверждения идентификатора . С помощью API параметров RP могут передавать IdP дополнительные параметры для запроса разрешений на доступ к ресурсам помимо базового входа. Пользователь авторизует эти разрешения через управляемый IdP поток пользовательского интерфейса, который запускается через Continuation API .
Чтобы использовать API, добавьте параметры в свойство params
как объект в вызове navigator.credentials.get()
.
let {token} = await navigator.credentials.get({
identity: {
providers: [{
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
// Key/value pairs that need to be passed from the
// RP to the IdP but that don't really play any role with
// the browser.
params: {
IDP_SPECIFIC_PARAM: '1',
foo: 'BAR',
ETC: 'MOAR',
scope: 'calendar.readonly photos.write',
}
},
}
});
Имена свойств в объекте params
начинаются с param_
. В приведенном выше примере свойство params содержит IDP_SPECIFIC_PARAM
как '1'
, foo
как 'BAR'
, ETC
как 'MOAR'
и scope
как 'calendar.readonly photos.write'
. Это будет переведено как param_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
в теле HTTP-запроса:
POST /fedcm_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false¶m_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
Получайте разрешения динамически
В общем, для пользователей наиболее полезно запрашивать разрешения тогда, когда они необходимы, а не тогда, когда разработчик считает, что их легче всего реализовать. Например, запрашивать разрешение на доступ к камере, когда пользователь собирается сделать фотографию, предпочтительнее, чем запрашивать разрешение, как только пользователь заходит на веб-сайт. Та же практика применяется и к ресурсам сервера. Запрашивайте разрешения только тогда, когда они необходимы пользователю. Это называется «динамическая авторизация».
Чтобы динамически запрашивать авторизацию с помощью FedCM, IdP может:
- Вызовите
navigator.credentials.get()
с необходимыми параметрами, которые IdP может понять, например,scope
. - Конечная точка утверждения идентификатора подтверждает, что пользователь уже вошел в систему, и отправляет в ответ URL-адрес
continue_on
. - Браузер открывает всплывающее окно со страницей разрешений IdP с запросом дополнительных разрешений, соответствующих запрошенным областям.
- После авторизации через
IdentityProvider.resolve()
от IdP окно закрывается, и исходный вызовnavigator.credentials.get()
RP получает соответствующий токен или код авторизации, чтобы RP мог обменять его на соответствующий токен доступа.
API полей
API Fields позволяет RP объявлять атрибуты учетной записи для запроса у IdP, чтобы браузер мог отображать правильный пользовательский интерфейс раскрытия информации в диалоговом окне FedCM; IdP несет ответственность за включение запрошенных полей в возвращаемый токен. Рассмотрим это, запрашивая «базовый профиль» в OpenID Connect, а не «области» в OAuth.
![Сообщение о раскрытии информации в режиме виджета.](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-126-with-disclosure-widget.jpg?authuser=8&hl=ru)
![Сообщение о раскрытии информации в режиме кнопки.](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-126-with-disclosure-button.jpg?authuser=8&hl=ru)
Чтобы использовать Fields API, добавьте параметры в свойство fields
в виде массива при вызове navigator.credentials.get()
. На данный момент поля могут содержать 'name'
, 'email'
и 'picture'
, но в будущем их можно расширить, чтобы включить больше значений.
Запрос с fields
будет выглядеть так:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
fields: ['name', 'email', 'picture'],
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
params: {
scope: 'drive.readonly calendar.readonly',
}
},
}
mediation: 'optional',
});
HTTP-запрос к конечной точке утверждения идентификатора включает параметр fields
, указанный RP, с параметром disclosure_text_shown
, установленным как true
если это не возвращающийся пользователь, и поля, которые браузер раскрыл пользователю в параметре disclosure_shown_for
:
POST /id_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=true&fields=email,name,picture&disclosure_shown_for=email,name,picture
Если RP требуется доступ к каким-либо дополнительным данным от IdP, например доступ к календарю, это должно быть обработано с помощью специального параметра, как указано выше. IdP возвращает URL-адрес continue_on
для запроса разрешения.
Если fields
— пустой массив, запрос будет выглядеть так:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
fields: [],
clientId: '1234',
configURL: 'https://idp.example/fedcm.json',
params: {
scope: 'drive.readonly calendar.readonly',
}
},
}
mediation: 'optional',
});
Если fields
— это пустой массив, пользовательский агент пропустит пользовательский интерфейс раскрытия.
![Сообщение о раскрытии информации не отображается в режиме виджета. В потоке кнопок пользовательский интерфейс раскрытия полностью пропускается.](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-126-without-disclosure-widget.jpg?authuser=8&hl=ru)
Это так, даже если ответ от конечной точки учетных записей не содержит идентификатор клиента, соответствующий RP в approved_clients
.
В этом случае disclosure_text_shown
, отправленное в конечную точку утверждения идентификатора, является ложным в теле HTTP:
POST /id_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false
Несколько configURL
Несколько URL-адресов configURL позволяют поставщикам удостоверений размещать несколько файлов конфигурации для одного поставщика удостоверений путем указания accounts_endpoint
и login_url
в общеизвестном файле так же, как и файлы конфигурации.
Если в общеизвестный файл добавляются accounts_endpoint
и login_url
, provider_urls
игнорируется, чтобы IdP мог поддерживать несколько файлов конфигурации. Если это не так, provider_urls
продолжает действовать, обеспечивая обратную совместимость.
Хорошо известный файл, поддерживающий несколько configURL, может выглядеть так:
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
Это позволяет нам:
- Поддерживайте обратную и прямую совместимость с существующими общеизвестными файлами и более ранними версиями браузеров, которые уже развернуты в реальных условиях.
- Имейте произвольное количество файлов конфигурации — при условии, что все они указывают на одни и те же
accounts_endpoint
иlogin_url
. - Не иметь возможности добавлять энтропию к запросу на выборку учетных данных, сделанному в
accounts_endpoint
, поскольку он должен быть указан на уровне «.well-known».
Поддержка нескольких configURL не является обязательной, и существующие реализации FedCM могут остаться прежними.
Пользовательские ярлыки учетной записи
Пользовательские метки учетных записей позволяют поставщикам удостоверений FedCM аннотировать учетные записи, чтобы RP могли их фильтровать, указав метку в файле конфигурации. Аналогичная фильтрация возможна с использованием API подсказок домена и API подсказок для входа, указав их в вызове navigator.credentials.get()
, но пользовательские метки учетной записи могут фильтровать пользователей, указав файл конфигурации, что особенно полезно при наличии нескольких configURL. используются. Пользовательские метки учетной записи также отличаются тем, что они предоставляются с сервера IdP, а не от RP, как подсказки для входа в систему или домена.
Пример
IdP поддерживает два configURL для потребителя и предприятия соответственно. Файл конфигурации потребителя имеет метку 'consumer'
, а файл конфигурации предприятия — метку 'enterprise'
.
При такой настройке известный файл включает в себя accounts_endpoint
и login_url
чтобы разрешить использование нескольких configURL.
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
Если accounts_endpoint
указан в известном файле, provider_urls
игнорируется. RP может напрямую указывать на соответствующие файлы конфигурации в вызове navigator.credentials.get()
.
Файл конфигурации потребителя находится по адресу https://idp.example/fedcm.json
и включает свойство accounts
, определяющее 'consumer'
с помощью include
.
{
"accounts_endpoint": "https://idp.example/accounts",
"client_metadata_endpoint": "/client_metadata",
"login_url": "https://idp.example/login",
"id_assertion_endpoint": "/assertion",
"accounts": {
"include": "consumer"
}
}
Корпоративный файл конфигурации находится по адресу https://idp.example/enterprise/fedcm.json
и включает в себя свойство accounts
, указывающее 'enterprise'
с помощью include
.
{
"accounts_endpoint": "https://idp.example/accounts",
"client_metadata_endpoint": "/enterprise/client_metadata",
"login_url": "https://idp.example/login",
"id_assertion_endpoint": "/assertion",
"accounts": {
"include": "enterprise"
}
}
Конечная точка общих учетных записей IdP (в этом примере https://idp.example/accounts
) возвращает список учетных записей, который включает свойство labels с назначенными labels
в массиве для каждой учетной записи. Ниже приведен пример ответа для пользователя, имеющего две учетные записи. Один для потребителя, а другой для предприятия:
{
"accounts": [{
"id": "123",
"given_name": "John",
"name": "John Doe",
"email": "john_doe@idp.example",
"picture": "https://idp.example/profile/123",
"labels": ["consumer"]
}], [{
"id": "4567",
"given_name": "Jane",
"name": "Jane Doe",
"email": "jane_doe@idp.example",
"picture": "https://idp.example/profile/4567",
"labels": ["enterprise"]
}]
}
Если RP хочет разрешить пользователям 'enterprise'
входа в систему, они могут указать configURL 'enterprise'
'https://idp.example/enterprise/fedcm.json'
в вызове navigator.credentials.get()
:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
clientId: '1234',
nonce: '234234',
configURL: 'https://idp.example/enterprise/fedcm.json',
},
}
});
В результате пользователю для входа доступен только идентификатор учетной записи '4567'
. Идентификатор учетной записи '123'
незаметно скрывается браузером, поэтому пользователю не будет предоставлена учетная запись, которая не поддерживается IdP на этом сайте.
Пробная версия Origin: FedCM как сигнал доверия для Storage Access API
Chrome 126 начинает тестирование FedCM в качестве сигнала доверия для Storage Access API . Благодаря этому изменению предварительное предоставление разрешения через FedCM становится веской причиной для автоматического одобрения запроса на доступ к хранилищу API-интерфейсами доступа к хранилищу .
Это полезно, когда встроенный iframe хочет получить доступ к персонализированным ресурсам: например, если idp.example встроен в rp.example и ему необходимо отобразить персонализированный ресурс. Если браузер ограничивает доступ к сторонним файлам cookie, даже если пользователь вошел в систему rp.example, используя idp.example с FedCM, встроенный iframe idp.example не сможет запрашивать персонализированные ресурсы, поскольку запросы не будут включать сторонние файлы cookie.
Для этого idp.example необходимо получить разрешение на доступ к хранилищу через iframe, встроенный в веб-сайт, и это можно получить только через запрос разрешения.
Поскольку FedCM является сигналом доверия для API доступа к хранилищу , проверки разрешений API доступа к хранилищу не только принимают разрешение, предоставленное запросом доступа к хранилищу, но также разрешение, предоставленное запросом FedCM.
// In top-level rp.example:
// Ensure FedCM permission has been granted.
const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://idp.example/fedcm.json',
clientId: '123',
}],
},
mediation: 'optional',
});
// In an embedded IdP iframe:
// No user gesture is needed to call this, and the call will be auto-granted.
await document.requestStorageAccess();
// This returns `true`.
const hasAccess = await document.hasStorageAccess();
После входа пользователя в систему с помощью FedCM разрешение предоставляется автоматически, пока активна аутентификация FedCM. Это означает, что после отключения пользователя при запросе разрешения отобразится запрос.
Примите участие в испытании происхождения
Вы можете попробовать пакет FedCM Continuation API локально, включив флаг Chrome chrome://flags#fedcm-authz
в Chrome 126 или более поздней версии. Вы также можете попробовать FedCM в качестве сигнала доверия для API доступа к хранилищу локально, включив #fedcm-with-storage-access-api
в Chrome 126 или более поздней версии.
Эти функции также доступны в виде пробных версий. Пробные версии Origin позволяют вам опробовать новые функции и оставить отзыв об их удобстве использования, практичности и эффективности. Для получения дополнительной информации ознакомьтесь с разделом Начало работы с пробными версиями Origin .
Чтобы попробовать исходную пробную версию пакета FedCM Continuation API , создайте два пробных токена источника:
- Зарегистрируйтесь на пробное занятие. Встройте токен в источник IdP .
- Зарегистрируйтесь для участия в пробной версии Origin, установив флажок соответствия сторонней версии. Следуйте инструкциям в разделе «Зарегистрируйте пробную версию стороннего источника для RP», чтобы внедрить токен для RP.
Если вы заинтересованы во включении Continuation API вместе с потоком кнопок , включите также пробную версию API-интерфейса режима кнопок :
- Зарегистрируйтесь для участия в пробной версии Origin в качестве третьего лица. Следуйте инструкциям в разделе Регистрация пробной версии стороннего источника для RP, чтобы внедрить токен для RP.
Чтобы попробовать FedCM в качестве сигнала доверия для пробной версии Storage Access API :
- Зарегистрируйтесь для участия в пробной версии Origin. Встройте токен в источник IdP .
Пробная версия исходного пакета Continuation API и FedCM в качестве сигнала доверия для пробной версии исходного API Storage Access доступны в Chrome 126.
Зарегистрируйте стороннюю пробную версию для RP
- Перейдите на страницу регистрации пробной версии Origin.
- Нажмите кнопку «Зарегистрироваться» и заполните форму, чтобы запросить токен.
- Введите источник IdP как Web Origin .
- Установите флажок Стороннее сопоставление, чтобы внедрить токен с помощью JavaScript в другие источники.
- Нажмите «Отправить» .
- Встройте выданный токен на сторонний сайт.
Чтобы встроить токен на сторонний веб-сайт, добавьте следующий код в библиотеку JavaScript или SDK поставщика удостоверений, обслуживаемую источником поставщика удостоверений.
const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);
Замените TOKEN_GOES_HERE
своим собственным токеном.