Узнайте, как использовать FedCM для федерации удостоверений, сохраняющей конфиденциальность.
FedCM (федеративное управление учетными данными) — это сохраняющий конфиденциальность подход к федеративным службам идентификации (например, «Войти с помощью...»), при котором пользователи могут входить на сайты, не передавая свою личную информацию службе идентификации или сайту.
Чтобы узнать больше о вариантах использования FedCM, пользовательских потоках и дорожной карте API, ознакомьтесь с введением в FedCM API .
Среда разработки FedCM
Для использования FedCM вам необходим безопасный контекст (HTTPS или локальный хост) как на IdP, так и на RP в Chrome.
Код отладки в Chrome на Android
Настройте и запустите сервер локально для отладки кода FedCM. Вы можете получить доступ к этому серверу в Chrome на устройстве Android, подключенном с помощью USB-кабеля с переадресацией портов.
Вы можете использовать DevTools на настольном компьютере для отладки Chrome на Android, следуя инструкциям в разделе Удаленная отладка устройств Android .
Блокируйте сторонние файлы cookie в Chrome
Вы можете проверить, как FedCM работает без сторонних файлов cookie в Chrome, прежде чем он будет применен.
Чтобы заблокировать сторонние файлы cookie, используйте режим инкогнито или выберите «Блокировать сторонние файлы cookie» в настройках рабочего стола по адресу chrome://settings/cookies
или на мобильном устройстве, перейдя в «Настройки» > «Настройки сайта» > «Файлы cookie» .
Использование API FedCM
Вы интегрируетесь с FedCM, создавая общеизвестный файл , файл конфигурации и конечные точки для списка учетных записей , выдачи утверждений и, при необходимости, метаданных клиента .
Отсюда FedCM предоставляет API-интерфейсы JavaScript, которые RP могут использовать для входа в систему с помощью IdP.
Создать известный файл
Чтобы предотвратить злоупотребление API трекерами , общеизвестный файл должен быть передан из /.well-known/web-identity
eTLD+1 IdP.
Например, если конечные точки IdP обслуживаются по адресу https://accounts.idp.example/
, они должны обслуживать общеизвестный файл по адресу https://idp.example/.well-known/web-identity
, а также Конфигурационный файл IdP . Вот пример содержимого известного файла:
{
"provider_urls": ["https://accounts.idp.example/config.json"]
}
Файл JSON должен содержать свойство provider_urls
с массивом URL-адресов файлов конфигурации IdP , которые могут быть указаны как часть пути configURL
в navigator.credentials.get
с помощью RP . Количество строк URL-адресов в массиве ограничено одной, но это может измениться по вашему отзыву в будущем.
Создайте файл конфигурации IdP и конечные точки.
Файл конфигурации IdP содержит список необходимых конечных точек для браузера. Поставщики удостоверений будут размещать этот файл конфигурации, а также необходимые конечные точки и URL-адреса. Все ответы JSON должны предоставляться с типом контента application/json
.
URL-адрес файла конфигурации определяется значениями, предоставленными вызову navigator.credentials.get
, выполняемому на RP .
const credential = await navigator.credentials.get({
identity: {
context: 'signup',
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******'
}]
}
});
const { token } = credential;
Укажите полный URL-адрес расположения файла конфигурации IdP в качестве configURL
. Когда navigator.credentials.get()
вызывается на RP, браузер получает файл конфигурации с помощью запроса GET
без заголовка Origin
или заголовка Referer
. Запрос не содержит файлов cookie и не следует перенаправлениям. Это эффективно не позволяет IdP узнать, кто сделал запрос и какой RP пытается подключиться. Например:
GET /config.json HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Sec-Fetch-Dest: webidentity
Браузер ожидает от IdP ответа в формате JSON, который включает в себя следующие свойства:
Свойство | Описание |
---|---|
accounts_endpoint (обязательно) | URL-адрес конечной точки учетной записи . |
client_metadata_endpoint (необязательно) | URL-адрес конечной точки метаданных клиента . |
id_assertion_endpoint (обязательно) | URL-адрес конечной точки утверждения идентификатора . |
disconnect (необязательно) | URL-адрес конечной точки отключения . |
login_url (обязательно) | URL-адрес страницы входа , на которой пользователь может войти в IdP. |
branding (по желанию) | Объект, содержащий различные варианты брендинга. |
branding.background_color (необязательно) | Параметр брендинга, устанавливающий цвет фона кнопки «Продолжить как...». Используйте соответствующий синтаксис CSS, а именно hex-color , hsl() , rgb() или named-color . |
branding.color (необязательно) | Параметр брендинга, определяющий цвет текста кнопки «Продолжить как...». Используйте соответствующий синтаксис CSS, а именно hex-color , hsl() , rgb() или named-color . |
branding.icons (необязательно) | Параметр брендинга, который устанавливает объект значка, отображаемый в диалоговом окне входа. Объект значка представляет собой массив с двумя параметрами:
|
RP может изменить строку в пользовательском интерфейсе диалогового окна FedCM с помощью identity.context
для navigator.credentials.get()
чтобы учесть предопределенные контексты аутентификации. Необязательным свойством может быть одно из "signin"
(по умолчанию), "signup"
, "use"
или "continue"
.
Вот пример тела ответа от IdP:
{
"accounts_endpoint": "/accounts.php",
"client_metadata_endpoint": "/client_metadata.php",
"id_assertion_endpoint": "/assertion.php",
"disconnect_endpoint": "/disconnect.php",
"login_url": "/login",
"branding": {
"background_color": "green",
"color": "#FFEEAA",
"icons": [{
"url": "https://idp.example/icon.ico",
"size": 25
}]
}
}
Как только браузер получает файл конфигурации, он отправляет последующие запросы конечным точкам IdP:
Конечная точка аккаунтов
Конечная точка учетных записей IdP возвращает список учетных записей, в которые пользователь в настоящее время вошел в IdP. Если поставщик удостоверений поддерживает несколько учетных записей, эта конечная точка вернет все зарегистрированные учетные записи.
Браузер отправляет запрос GET
с файлами cookie с SameSite=None
, но без параметра client_id
, заголовка Origin
или заголовка Referer
. Это эффективно не позволяет IdP узнать, на какую RP пользователь пытается войти. Например:
GET /accounts.php HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
Получив запрос, сервер должен:
- Убедитесь, что запрос содержит HTTP-заголовок
Sec-Fetch-Dest: webidentity
. - Сопоставьте файлы cookie сеанса с идентификаторами уже вошедших в систему учетных записей.
- Ответьте списком аккаунтов.
Браузер ожидает ответ JSON, который включает свойство accounts
с массивом информации об учетной записи со следующими свойствами:
Свойство | Описание |
---|---|
id (обязательно) | Уникальный идентификатор пользователя. |
name (обязательно) | Имя и фамилия пользователя. |
email (обязательно) | Адрес электронной почты пользователя. |
given_name (необязательно) | Имя пользователя. |
picture (необязательно) | URL-адрес изображения аватара пользователя. |
approved_clients (необязательно) | Массив идентификаторов клиентов RP, под которыми зарегистрировался пользователь. |
login_hints (необязательно) | Массив всех возможных типов фильтров, которые поддерживает IdP для указания учетной записи. RP может вызвать navigator.credentials.get() со свойством loginHint для выборочного отображения указанной учетной записи. |
domain_hints (необязательно) | Массив всех доменов, с которыми связана учетная запись. RP может вызвать navigator.credentials.get() со свойством domainHint для фильтрации учетных записей. |
Пример тела ответа:
{
"accounts": [{
"id": "1234",
"given_name": "John",
"name": "John Doe",
"email": "john_doe@idp.example",
"picture": "https://idp.example/profile/123",
"approved_clients": ["123", "456", "789"],
"login_hints": ["demo1", "demo1@idp.example"]
}, {
"id": "5678",
"given_name": "Johnny",
"name": "Johnny",
"email": "johnny@idp.example",
"picture": "https://idp.example/profile/456",
"approved_clients": ["abc", "def", "ghi"],
"login_hints": ["demo2", "demo2@idp.example"],
"domain_hints": ["corp.example"]
}]
}
Если пользователь не вошел в систему, ответьте HTTP 401 (неавторизованный).
Возвращенный список учетных записей используется браузером и не будет доступен RP.
Конечная точка метаданных клиента
Конечная точка метаданных клиента IdP возвращает метаданные проверяющей стороны, такие как политика конфиденциальности и условия обслуживания RP. RP должны заранее предоставить IdP ссылки на свою политику конфиденциальности и условия обслуживания. Эти ссылки отображаются в диалоговом окне входа, если пользователь еще не зарегистрировался на RP с IdP.
Браузер отправляет запрос GET
используя client_id
navigator.credentials.get
без файлов cookie. Например:
GET /client_metadata.php?client_id=1234 HTTP/1.1
Host: accounts.idp.example
Origin: https://rp.example/
Accept: application/json
Sec-Fetch-Dest: webidentity
Получив запрос, сервер должен:
- Определите RP для
client_id
. - Ответьте метаданными клиента.
Свойства конечной точки метаданных клиента включают в себя:
Свойство | Описание |
---|---|
privacy_policy_url (необязательно) | URL-адрес политики конфиденциальности RP. |
terms_of_service_url (необязательно) | URL-адрес условий обслуживания RP. |
Браузер ожидает ответа JSON от конечной точки:
{
"privacy_policy_url": "https://rp.example/privacy_policy.html",
"terms_of_service_url": "https://rp.example/terms_of_service.html",
}
Возвращенные метаданные клиента используются браузером и не будут доступны RP.
Конечная точка утверждения идентификатора
Конечная точка утверждения идентификатора IdP возвращает утверждение для вошедшего в систему пользователя. Когда пользователь входит на веб-сайт RP с помощью вызова navigator.credentials.get()
, браузер отправляет POST
запрос с файлами cookie с SameSite=None
и типом контента application/x-www-form-urlencoded
в эту конечную точку с следующую информацию:
Свойство | Описание |
---|---|
client_id (обязательно) | Идентификатор клиента RP. |
account_id (обязательно) | Уникальный идентификатор вошедшего пользователя. |
nonce (необязательно) | Запрос nonce, предоставленный RP. |
disclosure_text_shown | Результатом является строка "true" или "false" (а не логическое значение). Результатом будет "false" если текст раскрытия не был показан. Это происходит, когда идентификатор клиента RP был включен в список свойств approved_clients ответа от конечной точки учетных записей или если браузер наблюдал момент регистрации в прошлом при отсутствии approved_clients . |
is_auto_selected | Если на RP выполняется автоматическая повторная аутентификация , is_auto_selected указывает "true" . В противном случае "false" . Это полезно для поддержки большего количества функций, связанных с безопасностью. Например, некоторые пользователи могут предпочесть более высокий уровень безопасности, который требует явного посредничества пользователя при аутентификации. Если IdP получает запрос токена без такого посредничества, он может обработать запрос по-другому. Например, верните код ошибки, чтобы RP мог снова вызвать API FedCM с помощью mediation: required . |
Пример HTTP-заголовка:
POST /assertion.php HTTP/1.1
Host: accounts.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=Ct60bD&disclosure_text_shown=true&is_auto_selected=true
Получив запрос, сервер должен:
- Ответьте на запрос с помощью CORS (совместное использование ресурсов между источниками) .
- Убедитесь, что запрос содержит HTTP-заголовок
Sec-Fetch-Dest: webidentity
. - Сопоставьте заголовок
Origin
с источником RP, определеннымclient_id
. Отклонить, если они не совпадают. - Сопоставьте
account_id
с идентификатором уже вошедшей в систему учетной записи. Отклонить, если они не совпадают. - Ответьте жетоном. Если запрос отклонен, ответьте сообщением об ошибке .
Способ выдачи токена зависит от поставщика удостоверений, но, как правило, он подписывается такой информацией, как идентификатор учетной записи, идентификатор клиента, происхождение эмитента, nonce
, чтобы RP мог проверить подлинность токена.
Браузер ожидает ответ JSON, который включает следующее свойство:
Свойство | Описание |
---|---|
token (обязательно) | Токен — это строка, содержащая утверждения об аутентификации. |
{
"token": "***********"
}
Возвращенный токен передается браузером RP, чтобы RP могла проверить аутентификацию.
Вернуть ответ об ошибке
id_assertion_endpoint
также может возвращать ответ «ошибка», который имеет два необязательных поля:
-
code
: IdP может выбрать одну из известных ошибок из списка ошибок OAuth 2.0 (invalid_request
,unauthorized_client
,access_denied
,server_error
иtemporarily_unavailable
) или использовать любую произвольную строку. В последнем случае Chrome отображает пользовательский интерфейс ошибки с общим сообщением об ошибке и передает код RP. -
url
: идентифицирует удобочитаемую веб-страницу с информацией об ошибке, чтобы предоставить пользователям дополнительную информацию об ошибке. Это поле полезно для пользователей, поскольку браузеры не могут отображать подробные сообщения об ошибках в собственном пользовательском интерфейсе. Например, ссылки для следующих шагов, контактная информация службы поддержки клиентов и т. д. Если пользователь хочет узнать больше о деталях ошибки и о том, как ее исправить, он может посетить предоставленную страницу из пользовательского интерфейса браузера для получения более подробной информации. URL-адрес должен относиться к тому же сайту, что иconfigURL
IdP.
// id_assertion_endpoint response
{
"error" : {
"code": "access_denied",
"url" : "https://idp.example/error?type=access_denied"
}
}
Отключить конечную точку
Вызывая IdentityCredential.disconnect()
, браузер отправляет POST
запрос между источниками с файлами cookie с SameSite=None
и типом контента application/x-www-form-urlencoded
в эту конечную точку отключения со следующей информацией:
Свойство | Описание |
---|---|
account_hint | Подсказка для учетной записи IdP.. |
client_id | Идентификатор клиента RP. |
POST /disconnect.php HTTP/1.1
Host: idp.example
Origin: rp.example
Content-Type: application/x-www-form-urlencoded
Cookie: 0x123
Sec-Fetch-Dest: webidentity
account_hint=account456&client_id=rp123
Получив запрос, сервер должен:
- Ответьте на запрос с помощью CORS (совместное использование ресурсов между источниками) .
- Убедитесь, что запрос содержит HTTP-заголовок
Sec-Fetch-Dest: webidentity
. - Сопоставьте заголовок
Origin
с источником RP, определеннымclient_id
. Отклонить, если они не совпадают. - Сопоставьте
account_hint
с идентификаторами уже вошедших в систему учетных записей. - Отключите учетную запись пользователя от RP.
- Ответьте браузеру, указав идентифицированную информацию об учетной записи пользователя в формате JSON.
Пример полезной нагрузки JSON ответа выглядит следующим образом:
{
"account_id": "account456"
}
Вместо этого, если IdP желает, чтобы браузер отключил все учетные записи, связанные с RP, передайте строку, которая не соответствует ни одному идентификатору учетной записи, например "*"
.
URL-адрес входа
С помощью API статуса входа IdP должен сообщать браузеру статус входа пользователя. Однако статус может быть не синхронизирован, например, по истечении срока действия сеанса . В таком сценарии браузер может динамически разрешить пользователю входить в IdP через URL-адрес страницы входа, указанный в файле конфигурации idp login_url
.
В диалоговом окне FedCM отображается сообщение с предложением войти в систему, как показано на следующем рисунке.
Когда пользователь нажимает кнопку «Продолжить» , браузер открывает всплывающее окно со страницей входа в систему IdP.
Диалог представляет собой обычное окно браузера, в котором установлены основные файлы cookie. Что бы ни происходило в диалоговом окне, зависит от IdP, и нет доступных дескрипторов окон для отправки запроса на связь между источниками на странице RP. После того как пользователь вошел в систему, IdP должен:
- Отправьте заголовок
Set-Login: logged-in
или вызовите APInavigator.login.setStatus("logged-in")
чтобы сообщить браузеру, что пользователь выполнил вход. - Вызовите
IdentityProvider.close()
, чтобы закрыть диалоговое окно.
Сообщите браузеру о статусе входа пользователя в поставщика удостоверений.
API статуса входа — это механизм, с помощью которого веб-сайт, особенно поставщик удостоверений личности, сообщает браузеру статус входа пользователя в поставщика удостоверений. С помощью этого API браузер может сократить количество ненужных запросов к IdP и смягчить потенциальные атаки по времени.
IdP могут сообщать браузеру о статусе входа пользователя, отправляя HTTP-заголовок или вызывая API JavaScript, когда пользователь входит в систему IdP или когда пользователь выходит из всех своих учетных записей IdP. Для каждого IdP (идентифицированного по URL-адресу конфигурации) браузер сохраняет переменную с тремя состояниями, представляющую состояние входа в систему с возможными значениями: logged-in
, logged-out
» и unknown
. Состояние по умолчанию unknown
.
Чтобы сигнализировать о том, что пользователь вошел в систему, отправьте HTTP-заголовок Set-Login: logged-in
в навигации верхнего уровня или запрос подресурса того же сайта в источнике IdP:
Set-Login: logged-in
Альтернативно, вызовите API JavaScript navigator.login.setStatus("logged-in")
из источника IdP в навигации верхнего уровня:
navigator.login.setStatus("logged-in")
Эти вызовы записывают статус входа пользователя как logged-in
. Когда для статуса входа пользователя установлено logged-in
, RP, вызывающая FedCM, отправляет запросы к конечной точке учетных записей IdP и отображает доступные учетные записи пользователю в диалоговом окне FedCM.
Чтобы сигнализировать о том, что пользователь вышел из всех своих учетных записей, отправьте HTTP-заголовок Set-Login: logged-out
в навигации верхнего уровня или запрос подресурса того же сайта в источнике IdP:
Set-Login: logged-out
Альтернативно вызовите API JavaScript navigator.login.setStatus("logged-out")
из источника IdP в навигации верхнего уровня:
navigator.login.setStatus("logged-out")
Эти вызовы записывают статус входа пользователя в систему как logged-out
. Когда пользователь находится в состоянии logged-out
, вызов FedCM автоматически завершается неудачей без выполнения запроса к конечной точке учетных записей IdP.
unknown
статус устанавливается до того, как поставщик удостоверений отправит сигнал с помощью API статуса входа. Unknown
был введен для более удобного перехода, поскольку пользователь мог уже войти в IdP на момент поставки этого API. У IdP может не быть возможности сообщить об этом браузеру к моменту первого вызова FedCM. В этом случае Chrome отправляет запрос к конечной точке учетных записей IdP и обновляет статус на основе ответа от конечной точки учетных записей:
- Если конечная точка возвращает список активных учетных записей, обновите статус до
logged-in
и откройте диалоговое окно FedCM, чтобы отобразить эти учетные записи. - Если конечная точка не возвращает учетных записей, обновите статус до
logged-out
и откажитесь от вызова FedCM.
Разрешить пользователю войти в систему с помощью динамического процесса входа.
Несмотря на то, что IdP продолжает сообщать браузеру статус входа пользователя, он может быть не синхронизирован, например, по истечении срока действия сеанса. Браузер пытается отправить запрос с учетными данными в конечную точку учетных записей, когда статус входа — logged-in
, но сервер не возвращает учетные записи, поскольку сеанс больше не доступен. В таком случае браузер может динамически разрешить пользователю войти в IdP через всплывающее окно .
Войдите на проверяющую сторону с помощью поставщика удостоверений.
Как только конфигурация и конечные точки IdP станут доступны, RP могут вызвать navigator.credentials.get()
чтобы запросить разрешение пользователям войти в RP с помощью IdP.
Перед вызовом API необходимо подтвердить, что [FedCM доступен в браузере пользователя]. Чтобы проверить, доступен ли FedCM, оберните этот код вокруг вашей реализации FedCM:
if ('IdentityCredential' in window) {
// If the feature is available, take action
}
Чтобы запросить разрешение пользователям войти в IdP от RP, выполните, например, следующие действия:
const credential = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******'
}]
}
});
const { token } = credential;
Свойство providers
принимает массив объектов IdentityProvider
, которые имеют следующие свойства:
Свойство | Описание |
---|---|
configURL (обязательно) | Полный путь к файлу конфигурации IdP. |
clientId (обязательно) | Идентификатор клиента RP, выданный IdP. |
nonce (необязательно) | Случайная строка, гарантирующая выдачу ответа на этот конкретный запрос. Предотвращает повторные атаки. |
loginHint (необязательно) | Указав одно из значений login_hints предоставленных конечными точками учетных записей , диалоговое окно FedCM выборочно отображает указанную учетную запись. |
domainHint (необязательно) | Указав одно из значений domain_hints предоставленных конечными точками учетных записей , диалоговое окно FedCM выборочно отображает указанную учетную запись. |
Браузер по-разному обрабатывает варианты использования регистрации и входа в систему в зависимости от наличия approved_clients
в ответе от конечной точки списка учетных записей . Браузер не будет отображать текст раскрытия «Продолжить...», если пользователь уже зарегистрировался в RP.
Состояние регистрации определяется на основе того, выполнены или нет следующие условия:
- Если
approved_clients
включаютclientId
RP. - Если браузер помнит, что пользователь уже зарегистрировался на RP.
Когда RP вызывает navigator.credentials.get()
, происходят следующие действия:
- Браузер отправляет запросы и получает несколько документов:
- Известный файл и файл конфигурации IdP , которые объявляют конечные точки.
- Список аккаунтов .
- Необязательно: URL-адреса политики конфиденциальности и условий обслуживания RP, полученные из конечной точки метаданных клиента .
- Браузер отображает список учетных записей, которые пользователь может использовать для входа, а также условия обслуживания и политику конфиденциальности, если они доступны.
- Как только пользователь выбирает учетную запись для входа, запрос к конечной точке утверждения идентификатора отправляется IdP для получения токена.
- RP может проверить токен для аутентификации пользователя.
Ожидается, что RP будут поддерживать браузеры, которые не поддерживают FedCM, поэтому пользователи должны иметь возможность использовать существующий процесс входа, отличный от FedCM. До тех пор, пока сторонние файлы cookie не будут полностью прекращены, это не должно вызывать проблем.
Как только токен будет проверен сервером RP, RP может зарегистрировать пользователя или позволить ему войти в систему и начать новый сеанс.
API подсказок для входа в систему
После входа пользователя в систему иногда проверяющая сторона (RP) просит пользователя пройти повторную аутентификацию. Но пользователь может не быть уверен, какую учетную запись он использовал. Если RP может указать, с какой учетной записью войти в систему, пользователю будет проще выбрать учетную запись.
RP могут выборочно отображать конкретную учетную запись, вызывая navigator.credentials.get()
со свойством loginHint
с одним из значений login_hints
, полученным из конечной точки списка учетных записей , как показано в следующем примере кода:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "123",
nonce: nonce,
loginHint : "demo1@example.com"
}]
}
});
Если ни одна учетная запись не соответствует loginHint
, в диалоговом окне FedCM отображается приглашение для входа в систему, которое позволяет пользователю войти в учетную запись IdP, соответствующую подсказке, запрошенной RP. Когда пользователь нажимает на приглашение, открывается всплывающее окно с URL-адресом входа, указанным в файле конфигурации . Затем к ссылке добавляется подсказка для входа в систему и параметры запроса подсказки домена.
API подсказки домена
Бывают случаи, когда RP уже знает, что вход на сайт разрешен только учетным записям, связанным с определенным доменом. Это особенно распространено в корпоративных сценариях, где доступ к сайту ограничен корпоративным доменом. Чтобы обеспечить лучшее взаимодействие с пользователем, API FedCM позволяет RP отображать только те учетные записи, которые можно использовать для входа в RP. Это предотвращает сценарии, в которых пользователь пытается войти в RP, используя учетную запись за пределами корпоративного домена, но позже получает сообщение об ошибке (или молчание, если вход не сработал), поскольку не был использован правильный тип учетной записи.
RP могут выборочно отображать только совпадающие учетные записи, вызывая navigator.credentials.get()
со свойством domainHint
с одним из значений domain_hints
, полученным из конечной точки списка учетных записей , как показано в следующем примере кода:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "abc",
nonce: nonce,
domainHint : "corp.example"
}]
}
});
Если ни одна учетная запись не соответствует domainHint
, в диалоговом окне FedCM отображается приглашение для входа в систему, которое позволяет пользователю войти в учетную запись IdP, соответствующую подсказке, запрошенной RP. Когда пользователь нажимает на приглашение, открывается всплывающее окно с URL-адресом входа, указанным в файле конфигурации . Затем к ссылке добавляется подсказка для входа в систему и параметры запроса подсказки домена.
Показать сообщение об ошибке
Иногда поставщик удостоверений не может выдать токен по законным причинам, например, когда клиент неавторизован, сервер временно недоступен. Если IdP возвращает ответ «ошибка», RP может его перехватить, а Chrome уведомляет пользователя, показывая пользовательский интерфейс браузера с информацией об ошибке, предоставленной IdP.
try {
const cred = await navigator.credentials.get({
identity: {
providers: [
{
configURL: "https://idp.example/manifest.json",
clientId: "1234",
},
],
}
});
} catch (e) {
const code = e.code;
const url = e.url;
}
Автоматическая повторная аутентификация пользователей после первоначальной аутентификации
Автоматическая повторная аутентификация FedCM («автоматическая повторная аутентификация» вкратце) может позволить пользователям автоматически проходить повторную аутентификацию, когда они возвращаются после первоначальной аутентификации с использованием FedCM. «Первоначальная аутентификация» здесь означает, что пользователь создает учетную запись или входит на веб-сайт RP, впервые нажав кнопку «Продолжить как...» в диалоговом окне входа FedCM в одном и том же экземпляре браузера.
Хотя явный пользовательский опыт имеет смысл до того, как пользователь создал федеративную учетную запись, чтобы предотвратить отслеживание (что является одной из основных целей FedCM), он становится излишне громоздким после того, как пользователь прошел через это один раз: после того, как пользователь предоставляет разрешение на разрешение связи между RP и IdP, нет никаких преимуществ конфиденциальности или безопасности для принудительного подтверждения другого явного пользователя для чего-то, что он уже ранее подтвердил.
При автоматической повторной аутентификации браузер меняет свое поведение в зависимости от параметра, который вы указываете для mediation
при вызове navigator.credentials.get()
.
const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/fedcm.json",
clientId: "1234",
}],
},
mediation: 'optional', // this is the default
});
// `isAutoSelected` is `true` if auto-reauthn was performed.
const isAutoSelected = cred.isAutoSelected;
mediation
— это свойство API управления учетными данными . Оно ведет себя так же, как и для PasswordCredential и FederatedCredential , а также частично поддерживается PublicKeyCredential . Свойство принимает следующие четыре значения:
-
'optional'
(по умолчанию): если возможно, выполняется автоматическая повторная аутентификация, в противном случае требуется посредничество. Мы рекомендуем выбрать эту опцию на странице входа. -
'required'
: для продолжения всегда требуется посредничество, например нажатие кнопки «Продолжить» в пользовательском интерфейсе. Выберите этот вариант, если ожидается, что ваши пользователи будут явно предоставлять разрешение каждый раз, когда им необходимо пройти аутентификацию. -
'silent'
: если возможно, выполните автоматическую повторную аутентификацию, в противном случае — молчаливый сбой, не требуя посредничества. Мы рекомендуем выбирать этот параметр на страницах, отличных от специальной страницы входа, но на которых вы хотите, чтобы пользователи оставались в системе, например на странице товара на веб-сайте доставки или странице статьи на новостном веб-сайте. -
'conditional'
: используется для WebAuthn и на данный момент недоступен для FedCM.
При этом вызове автоматическая повторная аутентификация происходит при следующих условиях:
- FedCM доступен для использования. Например, пользователь не отключил FedCM ни глобально, ни для RP в настройках.
- Пользователь использовал только одну учетную запись с FedCM API для входа на веб-сайт в этом браузере.
- Пользователь входит в IdP с этой учетной записью.
- Автоматическая повторная аутентификация не произошла в течение последних 10 минут.
- RP не вызвал
navigator.credentials.preventSilentAccess()
после предыдущего входа в систему.
При выполнении этих условий попытка автоматической повторной аутентификации пользователя начинается сразу после вызова функции FedCM navigator.credentials.get()
.
При mediation: optional
автоматическая повторная аутентификация может быть недоступна по причинам, известным только браузеру; RP может проверить, выполняется ли автоматическая повторная аутентификация, проверив свойство isAutoSelected
.
Это полезно для оценки производительности API и соответствующего улучшения UX. Кроме того, когда он недоступен, пользователю может быть предложено войти в систему с явным посредничеством пользователя, которое представляет собой поток с mediation: required
.
Принудительное посредничество с помощью preventSilentAccess()
Автоматическая повторная аутентификация пользователей сразу после выхода из системы не обеспечит хорошего пользовательского опыта. Вот почему FedCM имеет 10-минутный период молчания после автоматической повторной аутентификации, чтобы предотвратить такое поведение. Это означает, что автоматическая повторная аутентификация происходит не чаще одного раза в 10 минут, если только пользователь не войдет в систему повторно в течение 10 минут. RP должна вызвать navigator.credentials.preventSilentAccess()
, чтобы явно запросить браузер отключить автоматическую повторную аутентификацию, когда пользователь явно выходит из RP, например, нажав кнопку выхода.
function signout() {
navigator.credentials.preventSilentAccess();
location.href = '/signout';
}
Пользователи могут отказаться от автоматической повторной аутентификации в настройках.
Пользователи могут отказаться от автоматической повторной аутентификации в меню настроек:
- В настольном Chrome перейдите в
chrome://password-manager/settings
> Войти автоматически. - В Android Chrome откройте «Настройки» > «Менеджер паролей» > коснитесь шестеренки в правом верхнем углу > «Автоматический вход».
Отключив переключатель, пользователь может полностью отказаться от автоматической повторной аутентификации. Этот параметр сохраняется и синхронизируется на всех устройствах, если пользователь вошел в учетную запись Google на экземпляре Chrome и включена синхронизация.
Отключите IdP от RP
Если пользователь ранее вошел в RP, используя IdP через FedCM, отношения запоминаются браузером локально в виде списка подключенных учетных записей. RP может инициировать отключение, вызвав функцию IdentityCredential.disconnect()
. Эту функцию можно вызвать из кадра RP верхнего уровня. RP необходимо передать configURL
, clientId
, который он использует в рамках IdP, и accountHint
для отключения IdP. Подсказка учетной записи может представлять собой произвольную строку, если конечная точка отключения может идентифицировать учетную запись, например адрес электронной почты или идентификатор пользователя, который не обязательно соответствует идентификатору учетной записи, предоставленному конечной точкой списка учетных записей:
// Disconnect an IdP account "account456" from the RP "https://idp.com/". This is invoked on the RP domain.
IdentityCredential.disconnect({
configURL: "https://idp.com/config.json",
clientId: "rp123",
accountHint: "account456"
});
IdentityCredential.disconnect()
возвращает Promise
. Это обещание может вызвать исключение по следующим причинам:
- Пользователь не вошел в систему RP, используя IdP через FedCM.
- API вызывается из iframe без политики разрешений FedCM.
- configURL недействителен или отсутствует конечная точка отключения.
- Проверка политики безопасности контента (CSP) не удалась.
- Имеется ожидающий запрос на отключение.
- Пользователь отключил FedCM в настройках браузера.
Когда конечная точка отключения IdP возвращает ответ , RP и IdP отключаются в браузере, и обещание разрешается. Идентификаторы отключенных учетных записей указаны в ответе от конечной точки отключения .
Вызов FedCM из iframe с перекрестным происхождением
FedCM можно вызвать из iframe с несколькими источниками, используя политику разрешений identity-credentials-get
, если родительский фрейм это позволяет. Для этого добавьте атрибутallow allow="identity-credentials-get"
к тегу iframe следующим образом:
<iframe src="https://fedcm-cross-origin-iframe.glitch.me" allow="identity-credentials-get"></iframe>
Вы можете увидеть это в действии на примере .
При необходимости, если родительский фрейм хочет ограничить источники для вызова FedCM, отправьте заголовок Permissions-Policy
со списком разрешенных источников.
Permissions-Policy: identity-credentials-get=(self "https://fedcm-cross-origin-iframe.glitch.me")
Вы можете узнать больше о том, как работает Политика разрешений, в разделе Управление функциями браузера с помощью Политики разрешений .
,Узнайте, как использовать FedCM для федерации удостоверений, сохраняющей конфиденциальность.
FedCM (федеративное управление учетными данными) — это сохраняющий конфиденциальность подход к федеративным службам идентификации (например, «Войти с помощью...»), при котором пользователи могут входить на сайты, не передавая свою личную информацию службе идентификации или сайту.
Чтобы узнать больше о вариантах использования FedCM, пользовательских потоках и дорожной карте API, ознакомьтесь с введением в FedCM API .
Среда разработки FedCM
Для использования FedCM вам необходим безопасный контекст (HTTPS или локальный хост) как на IdP, так и на RP в Chrome.
Код отладки в Chrome на Android
Настройте и запустите сервер локально для отладки кода FedCM. Вы можете получить доступ к этому серверу в Chrome на устройстве Android, подключенном с помощью USB-кабеля с переадресацией портов.
Вы можете использовать DevTools на настольном компьютере для отладки Chrome на Android, следуя инструкциям в разделе Удаленная отладка устройств Android .
Блокируйте сторонние файлы cookie в Chrome
Вы можете проверить, как FedCM работает без сторонних файлов cookie в Chrome, прежде чем он будет применен.
Чтобы заблокировать сторонние файлы cookie, используйте режим инкогнито или выберите «Блокировать сторонние файлы cookie» в настройках рабочего стола по адресу chrome://settings/cookies
или на мобильном устройстве, перейдя в «Настройки» > «Настройки сайта» > «Файлы cookie» .
Использование API FedCM
Вы интегрируетесь с FedCM, создавая общеизвестный файл , файл конфигурации и конечные точки для списка учетных записей , выдачи утверждений и, при необходимости, метаданных клиента .
Отсюда FedCM предоставляет API-интерфейсы JavaScript, которые RP могут использовать для входа в систему с помощью IdP.
Создать известный файл
Чтобы предотвратить злоупотребление API трекерами , общеизвестный файл должен быть передан из /.well-known/web-identity
eTLD+1 IdP.
Например, если конечные точки IdP обслуживаются по адресу https://accounts.idp.example/
, они должны обслуживать общеизвестный файл по адресу https://idp.example/.well-known/web-identity
, а также Файл конфигурации IdP . Вот пример содержимого известного файла:
{
"provider_urls": ["https://accounts.idp.example/config.json"]
}
Файл JSON должен содержать свойство provider_urls
с массивом URL-адресов файлов конфигурации IdP , которые могут быть указаны как часть пути configURL
в navigator.credentials.get
с помощью RP . Количество строк URL-адресов в массиве ограничено одной, но это может измениться по вашему отзыву в будущем.
Создайте файл конфигурации IdP и конечные точки.
Файл конфигурации IdP предоставляет список необходимых конечных точек для браузера. Поставщики удостоверений будут размещать этот файл конфигурации, а также необходимые конечные точки и URL-адреса. Все ответы JSON должны предоставляться с типом контента application/json
.
URL-адрес файла конфигурации определяется значениями, предоставленными вызову navigator.credentials.get
, выполняемому на RP .
const credential = await navigator.credentials.get({
identity: {
context: 'signup',
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******'
}]
}
});
const { token } = credential;
Укажите полный URL-адрес расположения файла конфигурации IdP в качестве configURL
. Когда navigator.credentials.get()
вызывается на RP, браузер получает файл конфигурации с помощью запроса GET
без заголовка Origin
или заголовка Referer
. Запрос не содержит файлов cookie и не следует перенаправлениям. Это эффективно не позволяет IdP узнать, кто сделал запрос и какой RP пытается подключиться. Например:
GET /config.json HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Sec-Fetch-Dest: webidentity
Браузер ожидает от IdP ответа в формате JSON, который включает в себя следующие свойства:
Свойство | Описание |
---|---|
accounts_endpoint (обязательно) | URL-адрес конечной точки учетной записи . |
client_metadata_endpoint (необязательно) | URL-адрес конечной точки метаданных клиента . |
id_assertion_endpoint (обязательно) | URL-адрес конечной точки утверждения идентификатора . |
disconnect (необязательно) | URL-адрес конечной точки отключения . |
login_url (обязательно) | URL-адрес страницы входа , на которой пользователь может войти в IdP. |
branding (по желанию) | Объект, содержащий различные варианты брендинга. |
branding.background_color (необязательно) | Параметр брендинга, устанавливающий цвет фона кнопки «Продолжить как...». Используйте соответствующий синтаксис CSS, а именно hex-color , hsl() , rgb() или named-color . |
branding.color (необязательно) | Параметр брендинга, определяющий цвет текста кнопки «Продолжить как...». Используйте соответствующий синтаксис CSS, а именно hex-color , hsl() , rgb() или named-color . |
branding.icons (необязательно) | Параметр брендинга, который устанавливает объект значка, отображаемый в диалоговом окне входа. Объект значка представляет собой массив с двумя параметрами:
|
RP может изменить строку в пользовательском интерфейсе диалогового окна FedCM с помощью identity.context
для navigator.credentials.get()
чтобы учесть предопределенные контексты аутентификации. Необязательным свойством может быть одно из "signin"
(по умолчанию), "signup"
, "use"
или "continue"
.
Вот пример тела ответа от IdP:
{
"accounts_endpoint": "/accounts.php",
"client_metadata_endpoint": "/client_metadata.php",
"id_assertion_endpoint": "/assertion.php",
"disconnect_endpoint": "/disconnect.php",
"login_url": "/login",
"branding": {
"background_color": "green",
"color": "#FFEEAA",
"icons": [{
"url": "https://idp.example/icon.ico",
"size": 25
}]
}
}
Как только браузер получает файл конфигурации, он отправляет последующие запросы конечным точкам IdP:
Конечная точка аккаунтов
Конечная точка учетных записей IdP возвращает список учетных записей, в которые пользователь в настоящее время вошел в IdP. Если поставщик удостоверений поддерживает несколько учетных записей, эта конечная точка вернет все зарегистрированные учетные записи.
Браузер отправляет запрос GET
с файлами cookie с SameSite=None
, но без параметра client_id
, заголовка Origin
или заголовка Referer
. Это эффективно не позволяет IdP узнать, на какую RP пользователь пытается войти. Например:
GET /accounts.php HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
Получив запрос, сервер должен:
- Убедитесь, что запрос содержит HTTP-заголовок
Sec-Fetch-Dest: webidentity
. - Сопоставьте файлы cookie сеанса с идентификаторами уже вошедших в систему учетных записей.
- Ответьте списком аккаунтов.
Браузер ожидает ответ JSON, который включает свойство accounts
с массивом информации об учетной записи со следующими свойствами:
Свойство | Описание |
---|---|
id (обязательно) | Уникальный идентификатор пользователя. |
name (обязательно) | Имя и фамилия пользователя. |
email (обязательно) | Адрес электронной почты пользователя. |
given_name (необязательно) | Имя пользователя. |
picture (необязательно) | URL-адрес изображения аватара пользователя. |
approved_clients (необязательно) | Массив идентификаторов клиентов RP, под которыми зарегистрировался пользователь. |
login_hints (необязательно) | Массив всех возможных типов фильтров, которые поддерживает IdP для указания учетной записи. RP может вызвать navigator.credentials.get() со свойством loginHint для выборочного отображения указанной учетной записи. |
domain_hints (необязательно) | Массив всех доменов, с которыми связана учетная запись. RP может вызвать navigator.credentials.get() со свойством domainHint для фильтрации учетных записей. |
Пример тела ответа:
{
"accounts": [{
"id": "1234",
"given_name": "John",
"name": "John Doe",
"email": "john_doe@idp.example",
"picture": "https://idp.example/profile/123",
"approved_clients": ["123", "456", "789"],
"login_hints": ["demo1", "demo1@idp.example"]
}, {
"id": "5678",
"given_name": "Johnny",
"name": "Johnny",
"email": "johnny@idp.example",
"picture": "https://idp.example/profile/456",
"approved_clients": ["abc", "def", "ghi"],
"login_hints": ["demo2", "demo2@idp.example"],
"domain_hints": ["corp.example"]
}]
}
Если пользователь не вошел в систему, ответьте HTTP 401 (неавторизованный).
Возвращенный список учетных записей используется браузером и не будет доступен RP.
Конечная точка метаданных клиента
Конечная точка метаданных клиента IdP возвращает метаданные проверяющей стороны, такие как политика конфиденциальности и условия обслуживания RP. RP должны заранее предоставить IdP ссылки на свою политику конфиденциальности и условия обслуживания. Эти ссылки отображаются в диалоговом окне входа, если пользователь еще не зарегистрировался на RP с IdP.
Браузер отправляет запрос GET
используя client_id
navigator.credentials.get
без файлов cookie. Например:
GET /client_metadata.php?client_id=1234 HTTP/1.1
Host: accounts.idp.example
Origin: https://rp.example/
Accept: application/json
Sec-Fetch-Dest: webidentity
Получив запрос, сервер должен:
- Определите RP для
client_id
. - Ответьте метаданными клиента.
Свойства конечной точки метаданных клиента включают в себя:
Свойство | Описание |
---|---|
privacy_policy_url (необязательно) | URL-адрес политики конфиденциальности RP. |
terms_of_service_url (необязательно) | URL-адрес условий обслуживания RP. |
Браузер ожидает ответа JSON от конечной точки:
{
"privacy_policy_url": "https://rp.example/privacy_policy.html",
"terms_of_service_url": "https://rp.example/terms_of_service.html",
}
Возвращенные метаданные клиента используются браузером и не будут доступны RP.
Конечная точка утверждения идентификатора
Конечная точка утверждения идентификатора IdP возвращает утверждение для вошедшего в систему пользователя. Когда пользователь входит на веб-сайт RP с помощью вызова navigator.credentials.get()
, браузер отправляет POST
запрос с файлами cookie с SameSite=None
и типом контента application/x-www-form-urlencoded
в эту конечную точку с следующую информацию:
Свойство | Описание |
---|---|
client_id (обязательно) | Идентификатор клиента RP. |
account_id (обязательно) | Уникальный идентификатор вошедшего пользователя. |
nonce (необязательно) | Запрос nonce, предоставленный RP. |
disclosure_text_shown | Результатом является строка "true" или "false" (а не логическое значение). Результатом будет "false" если текст раскрытия не был показан. Это происходит, когда идентификатор клиента RP был включен в список свойств approved_clients ответа от конечной точки учетных записей или если браузер наблюдал момент регистрации в прошлом при отсутствии approved_clients . |
is_auto_selected | Если на RP выполняется автоматическая повторная аутентификация , is_auto_selected указывает "true" . В противном случае "false" . Это полезно для поддержки большего количества функций, связанных с безопасностью. Например, некоторые пользователи могут предпочесть более высокий уровень безопасности, который требует явного посредничества пользователя при аутентификации. Если IdP получает запрос токена без такого посредничества, он может обработать запрос по-другому. Например, верните код ошибки, чтобы RP мог снова вызвать API FedCM с помощью mediation: required . |
Пример HTTP-заголовка:
POST /assertion.php HTTP/1.1
Host: accounts.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=Ct60bD&disclosure_text_shown=true&is_auto_selected=true
Получив запрос, сервер должен:
- Ответьте на запрос с помощью CORS (совместное использование ресурсов между источниками) .
- Убедитесь, что запрос содержит HTTP-заголовок
Sec-Fetch-Dest: webidentity
. - Сопоставьте заголовок
Origin
с источником RP, определеннымclient_id
. Отклонить, если они не совпадают. - Сопоставьте
account_id
с идентификатором уже вошедшей в систему учетной записи. Отклонить, если они не совпадают. - Ответьте жетоном. Если запрос отклонен, ответьте сообщением об ошибке .
Способ выдачи токена зависит от поставщика удостоверений, но, как правило, он подписывается такой информацией, как идентификатор учетной записи, идентификатор клиента, происхождение эмитента, nonce
, чтобы RP мог проверить подлинность токена.
Браузер ожидает ответ JSON, который включает следующее свойство:
Свойство | Описание |
---|---|
token (обязательно) | Токен — это строка, содержащая утверждения об аутентификации. |
{
"token": "***********"
}
Возвращенный токен передается браузером RP, чтобы RP могла проверить аутентификацию.
Вернуть ответ об ошибке
id_assertion_endpoint
также может возвращать ответ «ошибка», который имеет два необязательных поля:
-
code
: IdP может выбрать одну из известных ошибок из списка ошибок OAuth 2.0 (invalid_request
,unauthorized_client
,access_denied
,server_error
иtemporarily_unavailable
) или использовать любую произвольную строку. В последнем случае Chrome отображает пользовательский интерфейс ошибки с общим сообщением об ошибке и передает код RP. -
url
: идентифицирует удобочитаемую веб-страницу с информацией об ошибке, чтобы предоставить пользователям дополнительную информацию об ошибке. Это поле полезно для пользователей, поскольку браузеры не могут отображать подробные сообщения об ошибках в собственном пользовательском интерфейсе. Например, ссылки для следующих шагов, контактная информация службы поддержки клиентов и т. д. Если пользователь хочет узнать больше о деталях ошибки и о том, как ее исправить, он может посетить предоставленную страницу из пользовательского интерфейса браузера для получения более подробной информации. URL-адрес должен относиться к тому же сайту, что иconfigURL
IdP.
// id_assertion_endpoint response
{
"error" : {
"code": "access_denied",
"url" : "https://idp.example/error?type=access_denied"
}
}
Отключить конечную точку
Вызывая IdentityCredential.disconnect()
, браузер отправляет POST
запрос между источниками с файлами cookie с SameSite=None
и типом контента application/x-www-form-urlencoded
в эту конечную точку отключения со следующей информацией:
Свойство | Описание |
---|---|
account_hint | Подсказка для учетной записи IdP.. |
client_id | Идентификатор клиента RP. |
POST /disconnect.php HTTP/1.1
Host: idp.example
Origin: rp.example
Content-Type: application/x-www-form-urlencoded
Cookie: 0x123
Sec-Fetch-Dest: webidentity
account_hint=account456&client_id=rp123
Получив запрос, сервер должен:
- Ответьте на запрос с помощью CORS (совместное использование ресурсов между источниками) .
- Убедитесь, что запрос содержит HTTP-заголовок
Sec-Fetch-Dest: webidentity
. - Сопоставьте заголовок
Origin
с источником RP, определеннымclient_id
. Отклонить, если они не совпадают. - Сопоставьте
account_hint
с идентификаторами уже вошедших в систему учетных записей. - Отключите учетную запись пользователя от RP.
- Ответьте браузеру, указав идентифицированную информацию об учетной записи пользователя в формате JSON.
Пример полезной нагрузки JSON ответа выглядит следующим образом:
{
"account_id": "account456"
}
Вместо этого, если IdP желает, чтобы браузер отключил все учетные записи, связанные с RP, передайте строку, которая не соответствует ни одному идентификатору учетной записи, например "*"
.
URL-адрес входа
С помощью API статуса входа IdP должен сообщать браузеру статус входа пользователя. Однако статус может быть не синхронизирован, например, по истечении срока действия сеанса . В таком сценарии браузер может динамически разрешить пользователю входить в IdP через URL-адрес страницы входа, указанный в файле конфигурации idp login_url
.
В диалоговом окне FedCM отображается сообщение с предложением войти в систему, как показано на следующем рисунке.
Когда пользователь нажимает кнопку «Продолжить» , браузер открывает всплывающее окно со страницей входа в систему IdP.
Диалог представляет собой обычное окно браузера, в котором установлены основные файлы cookie. Что бы ни происходило в диалоговом окне, зависит от IdP, и нет доступных дескрипторов окон для отправки запроса на связь между источниками на странице RP. После того как пользователь вошел в систему, IdP должен:
- Отправьте заголовок
Set-Login: logged-in
или вызовите APInavigator.login.setStatus("logged-in")
чтобы сообщить браузеру, что пользователь выполнил вход. - Вызовите
IdentityProvider.close()
, чтобы закрыть диалоговое окно.
Сообщите браузеру о статусе входа пользователя в поставщика удостоверений.
API статуса входа — это механизм, с помощью которого веб-сайт, особенно поставщик удостоверений личности, сообщает браузеру статус входа пользователя в поставщика удостоверений. С помощью этого API браузер может сократить количество ненужных запросов к IdP и снизить потенциальные атаки по времени.
IdP могут сообщать браузеру о статусе входа пользователя, отправляя HTTP-заголовок или вызывая API JavaScript, когда пользователь входит в систему IdP или когда пользователь выходит из всех своих учетных записей IdP. Для каждого IdP (идентифицированного по URL-адресу конфигурации) браузер сохраняет переменную с тремя состояниями, представляющую состояние входа в систему с возможными значениями: logged-in
, logged-out
» и unknown
. Состояние по умолчанию unknown
.
Чтобы сигнализировать о том, что пользователь вошел в систему, отправьте HTTP-заголовок Set-Login: logged-in
в навигации верхнего уровня или запрос подресурса того же сайта в источнике IdP:
Set-Login: logged-in
Альтернативно, вызовите API JavaScript navigator.login.setStatus("logged-in")
из источника IdP в навигации верхнего уровня:
navigator.login.setStatus("logged-in")
Эти вызовы записывают статус входа пользователя как logged-in
. Когда для статуса входа пользователя установлено logged-in
, RP, вызывающая FedCM, отправляет запросы к конечной точке учетных записей IdP и отображает доступные учетные записи пользователю в диалоговом окне FedCM.
Чтобы сигнализировать о том, что пользователь вышел из всех своих учетных записей, отправьте HTTP-заголовок Set-Login: logged-out
в навигации верхнего уровня или запрос подресурса того же сайта в источнике IdP:
Set-Login: logged-out
Альтернативно вызовите API JavaScript navigator.login.setStatus("logged-out")
из источника IdP в навигации верхнего уровня:
navigator.login.setStatus("logged-out")
Эти вызовы записывают статус входа пользователя в систему как logged-out
. Когда пользователь находится в состоянии logged-out
, вызов FedCM автоматически завершается неудачей без выполнения запроса к конечной точке учетных записей IdP.
unknown
статус устанавливается до того, как поставщик удостоверений отправит сигнал с помощью API статуса входа. Unknown
был введен для более удобного перехода, поскольку пользователь мог уже войти в IdP на момент поставки этого API. У IdP может не быть возможности сообщить об этом браузеру к моменту первого вызова FedCM. В этом случае Chrome отправляет запрос к конечной точке учетных записей IdP и обновляет статус на основе ответа от конечной точки учетных записей:
- Если конечная точка возвращает список активных учетных записей, обновите статус до
logged-in
и откройте диалоговое окно FedCM, чтобы отобразить эти учетные записи. - Если конечная точка не возвращает учетных записей, обновите статус до
logged-out
и откажитесь от вызова FedCM.
Разрешить пользователю войти в систему с помощью динамического процесса входа.
Несмотря на то, что IdP продолжает сообщать браузеру статус входа пользователя, он может быть не синхронизирован, например, по истечении срока действия сеанса. Браузер пытается отправить запрос с учетными данными в конечную точку учетных записей, когда статус входа — logged-in
, но сервер не возвращает учетные записи, поскольку сеанс больше не доступен. В таком случае браузер может динамически разрешить пользователю войти в IdP через всплывающее окно .
Войдите на проверяющую сторону с помощью поставщика удостоверений.
Как только конфигурация и конечные точки IdP станут доступны, RP могут вызвать navigator.credentials.get()
чтобы запросить разрешение пользователям войти в RP с помощью IdP.
Перед вызовом API необходимо подтвердить, что [FedCM доступен в браузере пользователя]. Чтобы проверить, доступен ли FedCM, оберните этот код вокруг вашей реализации FedCM:
if ('IdentityCredential' in window) {
// If the feature is available, take action
}
Чтобы запросить разрешение пользователям войти в IdP от RP, выполните, например, следующие действия:
const credential = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******'
}]
}
});
const { token } = credential;
Свойство providers
принимает массив объектов IdentityProvider
, которые имеют следующие свойства:
Свойство | Описание |
---|---|
configURL (обязательно) | Полный путь к файлу конфигурации IdP. |
clientId (обязательно) | Идентификатор клиента RP, выданный IdP. |
nonce (необязательно) | Случайная строка, гарантирующая выдачу ответа на этот конкретный запрос. Предотвращает повторные атаки. |
loginHint (необязательно) | Указав одно из значений login_hints предоставленных конечными точками учетных записей , диалоговое окно FedCM выборочно отображает указанную учетную запись. |
domainHint (необязательно) | Указав одно из значений domain_hints предоставленных конечными точками учетных записей , диалоговое окно FedCM выборочно отображает указанную учетную запись. |
Браузер по-разному обрабатывает варианты использования регистрации и входа в систему в зависимости от наличия approved_clients
в ответе от конечной точки списка учетных записей . Браузер не будет отображать текст раскрытия «Продолжить...», если пользователь уже зарегистрировался в RP.
Состояние регистрации определяется на основе того, выполнены или нет следующие условия:
- Если
approved_clients
включаютclientId
RP. - Если браузер помнит, что пользователь уже зарегистрировался на RP.
Когда RP вызывает navigator.credentials.get()
, происходят следующие действия:
- Браузер отправляет запросы и получает несколько документов:
- Известный файл и файл конфигурации IdP , которые объявляют конечные точки.
- Список аккаунтов .
- Необязательно: URL-адреса политики конфиденциальности и условий обслуживания RP, полученные из конечной точки метаданных клиента .
- Браузер отображает список учетных записей, которые пользователь может использовать для входа, а также условия обслуживания и политику конфиденциальности, если они доступны.
- Как только пользователь выбирает учетную запись для входа, запрос к конечной точке утверждения идентификатора отправляется IdP для получения токена.
- RP может проверить токен для аутентификации пользователя.
Ожидается, что RP будут поддерживать браузеры, которые не поддерживают FedCM, поэтому пользователи должны иметь возможность использовать существующий процесс входа, отличный от FedCM. До тех пор, пока сторонние файлы cookie не будут полностью прекращены, это не должно вызывать проблем.
Как только токен будет проверен сервером RP, RP может зарегистрировать пользователя или позволить ему войти в систему и начать новый сеанс.
API подсказок для входа в систему
После входа пользователя в систему иногда проверяющая сторона (RP) просит пользователя пройти повторную аутентификацию. Но пользователь может не быть уверен, какую учетную запись он использовал. Если RP может указать, с какой учетной записью войти в систему, пользователю будет проще выбрать учетную запись.
RP могут выборочно отображать конкретную учетную запись, вызывая navigator.credentials.get()
со свойством loginHint
с одним из значений login_hints
, полученным из конечной точки списка учетных записей , как показано в следующем примере кода:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "123",
nonce: nonce,
loginHint : "demo1@example.com"
}]
}
});
Если ни одна учетная запись не соответствует loginHint
, в диалоговом окне FedCM отображается приглашение для входа в систему, которое позволяет пользователю войти в учетную запись IdP, соответствующую подсказке, запрошенной RP. Когда пользователь нажимает на приглашение, открывается всплывающее окно с URL-адресом входа, указанным в файле конфигурации . Затем к ссылке добавляется подсказка для входа в систему и параметры запроса подсказки домена.
API подсказки домена
Бывают случаи, когда RP уже знает, что вход на сайт разрешен только учетным записям, связанным с определенным доменом. Это особенно распространено в корпоративных сценариях, где доступ к сайту ограничен корпоративным доменом. Чтобы обеспечить лучшее взаимодействие с пользователем, API FedCM позволяет RP отображать только те учетные записи, которые можно использовать для входа в RP. Это предотвращает сценарии, в которых пользователь пытается войти в RP, используя учетную запись за пределами корпоративного домена, но позже получает сообщение об ошибке (или молчание, если вход не сработал), поскольку не был использован правильный тип учетной записи.
RP могут выборочно отображать только совпадающие учетные записи, вызывая navigator.credentials.get()
со свойством domainHint
с одним из значений domain_hints
, полученным из конечной точки списка учетных записей , как показано в следующем примере кода:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "abc",
nonce: nonce,
domainHint : "corp.example"
}]
}
});
Если ни одна учетная запись не соответствует domainHint
, в диалоговом окне FedCM отображается приглашение для входа в систему, которое позволяет пользователю войти в учетную запись IdP, соответствующую подсказке, запрошенной RP. Когда пользователь нажимает на приглашение, открывается всплывающее окно с URL-адресом входа, указанным в файле конфигурации . Затем к ссылке добавляется подсказка для входа в систему и параметры запроса подсказки домена.
Показать сообщение об ошибке
Иногда поставщик удостоверений не может выдать токен по законным причинам, например, когда клиент неавторизован, сервер временно недоступен. Если IdP возвращает ответ «ошибка», RP может его перехватить, а Chrome уведомляет пользователя, показывая пользовательский интерфейс браузера с информацией об ошибке, предоставленной IdP.
try {
const cred = await navigator.credentials.get({
identity: {
providers: [
{
configURL: "https://idp.example/manifest.json",
clientId: "1234",
},
],
}
});
} catch (e) {
const code = e.code;
const url = e.url;
}
Автоматическая повторная аутентификация пользователей после первоначальной аутентификации
Автоматическая повторная аутентификация FedCM («автоматическая повторная аутентификация» вкратце) может позволить пользователям автоматически проходить повторную аутентификацию, когда они возвращаются после первоначальной аутентификации с использованием FedCM. «Первоначальная аутентификация» здесь означает, что пользователь создает учетную запись или входит на веб-сайт RP, впервые нажав кнопку «Продолжить как...» в диалоговом окне входа FedCM в одном и том же экземпляре браузера.
Хотя явный пользовательский опыт имеет смысл до того, как пользователь создал федеративную учетную запись, чтобы предотвратить отслеживание (что является одной из основных целей FedCM), он становится излишне громоздким после того, как пользователь прошел через это один раз: после того, как пользователь предоставляет разрешение на разрешение связи между RP и IdP, нет никаких преимуществ конфиденциальности или безопасности для принудительного подтверждения другого явного пользователя для чего-то, что он уже ранее подтвердил.
При автоматической повторной аутентификации браузер меняет свое поведение в зависимости от параметра, который вы указываете для mediation
при вызове navigator.credentials.get()
.
const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/fedcm.json",
clientId: "1234",
}],
},
mediation: 'optional', // this is the default
});
// `isAutoSelected` is `true` if auto-reauthn was performed.
const isAutoSelected = cred.isAutoSelected;
mediation
— это свойство API управления учетными данными . Оно ведет себя так же, как и для PasswordCredential и FederatedCredential , а также частично поддерживается PublicKeyCredential . Свойство принимает следующие четыре значения:
-
'optional'
(по умолчанию): если возможно, выполняется автоматическая повторная аутентификация, в противном случае требуется посредничество. Мы рекомендуем выбрать эту опцию на странице входа. -
'required'
: для продолжения всегда требуется посредничество, например нажатие кнопки «Продолжить» в пользовательском интерфейсе. Выберите этот вариант, если ожидается, что ваши пользователи будут явно предоставлять разрешение каждый раз, когда им необходимо пройти аутентификацию. -
'silent'
: если возможно, выполните автоматическую повторную аутентификацию, в противном случае — молчаливый сбой, не требуя посредничества. Мы рекомендуем выбирать этот параметр на страницах, отличных от специальной страницы входа, но на которых вы хотите, чтобы пользователи оставались в системе, например на странице товара на веб-сайте доставки или странице статьи на новостном веб-сайте. -
'conditional'
: используется для WebAuthn и на данный момент недоступен для FedCM.
При этом вызове автоматическая повторная аутентификация происходит при следующих условиях:
- FedCM доступен для использования. Например, пользователь не отключил FedCM ни глобально, ни для RP в настройках.
- Пользователь использовал только одну учетную запись с FedCM API для входа на веб-сайт в этом браузере.
- Пользователь входит в IdP с этой учетной записью.
- Автоматическая повторная аутентификация не произошла в течение последних 10 минут.
- RP не вызвал
navigator.credentials.preventSilentAccess()
после предыдущего входа в систему.
При выполнении этих условий попытка автоматической повторной аутентификации пользователя начинается сразу после вызова функции FedCM navigator.credentials.get()
.
При mediation: optional
автоматическая повторная аутентификация может быть недоступна по причинам, известным только браузеру; RP может проверить, выполняется ли автоматическая повторная аутентификация, проверив свойство isAutoSelected
.
Это полезно для оценки производительности API и соответствующего улучшения UX. Кроме того, когда он недоступен, пользователю может быть предложено войти в систему с явным посредничеством пользователя, которое представляет собой поток с mediation: required
.
Принудительное посредничество с помощью preventSilentAccess()
Автоматическая повторная аутентификация пользователей сразу после выхода из системы не обеспечит хорошего пользовательского опыта. Вот почему FedCM имеет 10-минутный период молчания после автоматической повторной аутентификации, чтобы предотвратить такое поведение. Это означает, что автоматическая повторная аутентификация происходит не чаще одного раза в 10 минут, если только пользователь не войдет в систему повторно в течение 10 минут. RP должна вызвать navigator.credentials.preventSilentAccess()
, чтобы явно запросить браузер отключить автоматическую повторную аутентификацию, когда пользователь явно выходит из RP, например, нажав кнопку выхода.
function signout() {
navigator.credentials.preventSilentAccess();
location.href = '/signout';
}
Пользователи могут отказаться от автоматической повторной аутентификации в настройках.
Пользователи могут отказаться от автоматической повторной аутентификации в меню настроек:
- В настольном Chrome перейдите в
chrome://password-manager/settings
> Войти автоматически. - В Android Chrome откройте «Настройки» > «Менеджер паролей» > коснитесь шестеренки в правом верхнем углу > «Автоматический вход».
Отключив переключатель, пользователь может полностью отказаться от автоматической повторной аутентификации. Этот параметр сохраняется и синхронизируется на всех устройствах, если пользователь вошел в учетную запись Google на экземпляре Chrome и включена синхронизация.
Отключите IdP от RP
Если пользователь ранее вошел в RP, используя IdP через FedCM, отношения запоминаются браузером локально в виде списка подключенных учетных записей. RP может инициировать отключение, вызвав функцию IdentityCredential.disconnect()
. Эту функцию можно вызвать из кадра RP верхнего уровня. RP необходимо передать configURL
, clientId
, который он использует в рамках IdP, и accountHint
для отключения IdP. Подсказка учетной записи может представлять собой произвольную строку, если конечная точка отключения может идентифицировать учетную запись, например адрес электронной почты или идентификатор пользователя, который не обязательно соответствует идентификатору учетной записи, предоставленному конечной точкой списка учетных записей:
// Disconnect an IdP account "account456" from the RP "https://idp.com/". This is invoked on the RP domain.
IdentityCredential.disconnect({
configURL: "https://idp.com/config.json",
clientId: "rp123",
accountHint: "account456"
});
IdentityCredential.disconnect()
возвращает Promise
. Это обещание может вызвать исключение по следующим причинам:
- Пользователь не вошел в систему RP, используя IdP через FedCM.
- API вызывается из iframe без политики разрешений FedCM.
- configURL недействителен или отсутствует конечная точка отключения.
- Проверка политики безопасности контента (CSP) не удалась.
- Имеется ожидающий запрос на отключение.
- Пользователь отключил FedCM в настройках браузера.
Когда конечная точка отключения IdP возвращает ответ , RP и IdP отключаются в браузере, и обещание разрешается. Идентификаторы отключенных учетных записей указаны в ответе от конечной точки отключения .
Вызов FedCM из iframe с перекрестным происхождением
FedCM можно вызвать из iframe с несколькими источниками, используя политику разрешений identity-credentials-get
, если родительский фрейм это позволяет. Для этого добавьте атрибутallow allow="identity-credentials-get"
к тегу iframe следующим образом:
<iframe src="https://fedcm-cross-origin-iframe.glitch.me" allow="identity-credentials-get"></iframe>
Вы можете увидеть это в действии на примере .
При необходимости, если родительский фрейм хочет ограничить источники для вызова FedCM, отправьте заголовок Permissions-Policy
со списком разрешенных источников.
Permissions-Policy: identity-credentials-get=(self "https://fedcm-cross-origin-iframe.glitch.me")
Вы можете узнать больше о том, как работает Политика разрешений, в разделе Управление функциями браузера с помощью Политики разрешений .