Руководство разработчика API федеративного управления учетными данными,Руководство разработчика API федеративного управления учетными данными

Узнайте, как использовать FedCM для федерации удостоверений, сохраняющей конфиденциальность.

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

Чтобы узнать больше о вариантах использования FedCM, пользовательских потоках и дорожной карте API, ознакомьтесь с введением в FedCM API .

Среда разработки FedCM

Для использования FedCM вам необходим безопасный контекст (HTTPS или локальный хост) как на IdP, так и на RP в Chrome.

Код отладки в Chrome на Android

Настройте и запустите сервер локально для отладки кода FedCM. Вы можете получить доступ к этому серверу в Chrome на устройстве Android, подключенном с помощью USB-кабеля с переадресацией портов.

Вы можете использовать DevTools на настольном компьютере для отладки Chrome на Android, следуя инструкциям в разделе Удаленная отладка устройств Android .

Блокируйте сторонние файлы cookie в Chrome

Имитируйте поэтапный отказ от сторонних файлов cookie, настроив Chrome на их блокировку.
Имитируйте поэтапный отказ от сторонних файлов 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 (необязательно) Параметр брендинга, который устанавливает объект значка, отображаемый в диалоговом окне входа. Объект значка представляет собой массив с двумя параметрами:
  • url (обязательно): URL-адрес изображения значка. Это не поддерживает изображения SVG.
  • size (необязательно): размеры значка, предполагаемые приложением как квадратные и с одним разрешением. Это число должно быть больше или равно 25.

RP может изменить строку в пользовательском интерфейсе диалогового окна FedCM с помощью identity.context для navigator.credentials.get() чтобы учесть предопределенные контексты аутентификации. Необязательным свойством может быть одно из "signin" (по умолчанию), "signup" , "use" или "continue" .

Как брендинг применяется к диалоговому окну FedCM
Как брендинг применяется к диалоговому окну FedCM

Вот пример тела ответа от 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

Получив запрос, сервер должен:

  1. Убедитесь, что запрос содержит HTTP-заголовок Sec-Fetch-Dest: webidentity .
  2. Сопоставьте файлы cookie сеанса с идентификаторами уже вошедших в систему учетных записей.
  3. Ответьте списком аккаунтов.

Браузер ожидает ответ 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

Получив запрос, сервер должен:

  1. Определите RP для client_id .
  2. Ответьте метаданными клиента.

Свойства конечной точки метаданных клиента включают в себя:

Свойство Описание
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

Получив запрос, сервер должен:

  1. Ответьте на запрос с помощью CORS (Cross-Origin Resource Sharing) .
  2. Убедитесь, что запрос содержит HTTP-заголовок Sec-Fetch-Dest: webidentity .
  3. Сопоставьте заголовок Origin с источником RP, определяемым client_id . Отклонить, если они не совпадают.
  4. Сопоставьте account_id с идентификатором уже вошедшей в систему учетной записи. Отклонить, если они не совпадают.
  5. Ответьте жетоном. Если запрос отклонен, ответьте сообщением об ошибке .

Способ выдачи токена зависит от поставщика удостоверений, но, как правило, он подписывается такой информацией, как идентификатор учетной записи, идентификатор клиента, происхождение эмитента, 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

Получив запрос, сервер должен:

  1. Ответьте на запрос с помощью CORS (Cross-Origin Resource Sharing) .
  2. Убедитесь, что запрос содержит HTTP-заголовок Sec-Fetch-Dest: webidentity .
  3. Сопоставьте заголовок Origin с источником RP, определяемым client_id . Отклонить, если они не совпадают.
  4. Сопоставьте account_hint с идентификаторами уже вошедших в систему учетных записей.
  5. Отключите учетную запись пользователя от RP.
  6. Ответьте браузеру, указав идентифицированную информацию об учетной записи пользователя в формате JSON.

Пример полезной нагрузки JSON ответа выглядит следующим образом:

{
  "account_id": "account456"
}

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

URL-адрес входа

С помощью API статуса входа IdP должен сообщать браузеру статус входа пользователя. Однако статус может быть не синхронизирован, например, по истечении срока действия сеанса . В таком сценарии браузер может динамически разрешить пользователю входить в IdP через URL-адрес страницы входа, указанный в файле конфигурации idp login_url .

В диалоговом окне FedCM отображается сообщение с предложением войти в систему, как показано на следующем рисунке.

А
Диалоговое окно FedCM с предложением войти в IdP.

Когда пользователь нажимает кнопку «Продолжить» , браузер открывает всплывающее окно со страницей входа в систему IdP.

Ан
Пример диалогового окна, отображаемого после нажатия кнопки входа в систему IdP.

Диалог представляет собой обычное окно браузера, в котором установлены основные файлы cookie. Что бы ни происходило в диалоговом окне, зависит от IdP, и нет доступных дескрипторов окон для отправки запроса на связь между источниками на странице RP. После того как пользователь вошел в систему, IdP должен:

  • Отправьте заголовок Set-Login: logged-in или вызовите API navigator.login.setStatus("logged-in") чтобы сообщить браузеру, что пользователь выполнил вход.
  • Вызовите IdentityProvider.close() , чтобы закрыть диалоговое окно.
А
Пользователь входит в RP после входа в IdP с помощью FedCM.

Сообщите браузеру о статусе входа пользователя в поставщика удостоверений.

API статуса входа — это механизм, с помощью которого веб-сайт, особенно поставщик удостоверений личности, сообщает браузеру статус входа пользователя в поставщика удостоверений. С помощью этого API браузер может сократить количество ненужных запросов к 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 с помощью FedCM.

Когда RP вызывает navigator.credentials.get() , происходят следующие действия:

  1. Браузер отправляет запросы и получает несколько документов:
    1. Известный файл и файл конфигурации IdP , которые объявляют конечные точки.
    2. Список аккаунтов .
    3. Необязательно: URL-адреса политики конфиденциальности и условий обслуживания RP, полученные из конечной точки метаданных клиента .
  2. Браузер отображает список учетных записей, которые пользователь может использовать для входа, а также условия обслуживания и политику конфиденциальности, если они доступны.
  3. Как только пользователь выбирает учетную запись для входа, запрос к конечной точке утверждения идентификатора отправляется IdP для получения токена.
  4. RP может проверить токен для аутентификации пользователя.
вызов API входа в систему
вызов API входа в систему

Ожидается, что 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-адресом входа, указанным в файле конфигурации . Затем к ссылке добавляется подсказка для входа в систему и параметры запроса подсказки домена.

Пример запроса на вход в систему, когда ни одна учетная запись не соответствует доменуHint.
Пример запроса на вход в систему, когда ни одна учетная запись не соответствует domainHint .

Показать сообщение об ошибке

Иногда поставщик удостоверений не может выдать токен по законным причинам, например, когда клиент не авторизован, сервер временно недоступен. Если IdP возвращает ответ «ошибка», RP может его перехватить, а Chrome уведомляет пользователя, показывая пользовательский интерфейс браузера с информацией об ошибке, предоставленной IdP.

А
Диалоговое окно FedCM, показывающее сообщение об ошибке после неудачной попытки входа пользователя. Строка связана с типом ошибки .
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 .

Пользователь автоматически проходит повторную аутентификацию через FedCM.

Принудительное посредничество с помощью 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.
  • Конфигурация недействительна или отсутствует конечная точка отключения.
  • Политика безопасности контента (CSP) Проверка не удастся.
  • Существует ожидающий запрос отключения.
  • Пользователь отключил FedCM в настройках браузера.

Когда конечная точка отключения IDP возвращает ответ , RP и IDP отключены в браузере, и обещание разрешено. Идентификатор отключенных счетов указан в ответе от конечной точки отключения .

Позвоните FedCM из перекрестного происхождения

FEDCM может быть вызван из перекрестного происхождения IFRAME, используя политику разрешений identity-credentials-get , если это позволяет родительская кадр. Для этого добавьте атрибут 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")

Вы можете узнать больше о том, как работает политика разрешений в управлении функциями браузера с политикой разрешений .