Spec-Zone.ru › Web APIs

Интеграция поставщика удостоверений с FedCM

В этой статье подробно описаны все шаги, которые должен предпринять поставщик удостоверений (IdP), чтобы интегрироваться с API Federated Credential Management (FedCM).

Шаги интеграции IdP

Для интеграции с FedCM IdP необходимо выполнить следующие действия:

  1. Предоставить файл с общедоступной информацией для идентификации IdP.
  2. Предоставить конфигурационный файл и конечные точки для списков учетных записей и выдачи утверждений (и, необязательно, метаданных клиента).
  3. Обновить статус входа в систему с помощью API статуса входа.

Предоставление файла с общедоступной информацией

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

Файл с общедоступной информацией запрашивается с помощью неуполномоченного запроса GET, который не обрабатывает перенаправления. Это фактически предотвращает получение IdP информации о том, кто инициировал запрос и какой RP пытается подключиться.

Файл с общедоступной информацией должен быть размещен в зоне eTLD+1 IdP по адресу /.well-known/web-identity. Например, если конечные точки IdP обслуживаются по адресу https://accounts.idp.example/, они должны размещать файл с общедоступной информацией по адресу https://idp.example/.well-known/web-identity. Содержимое файла с общедоступной информацией должно иметь следующую структуру JSON:

{
  "provider_urls": ["https://accounts.idp.example/config.json"]
}

Член provider_urls должен содержать массив URL-адресов, указывающих на допустимые конфигурационные файлы IdP, которые могут использоваться RP для взаимодействия с IdP. Длина массива в настоящее время ограничена одним элементом.

Заголовок HTTP Sec-Fetch-Dest

Все запросы, отправляемые браузером через FedCM, включают заголовок Sec-Fetch-Dest: webidentity. Все конечные точки IdP, которые принимают запросы с учётными данными (т.е. accounts_endpoint и id_assertion_endpoint), должны подтвердить наличие этого заголовка, чтобы защититься от атак CSRF.

Предоставление конфигурационного файла и конечных точек

Конфигурационный файл IdP предоставляет список конечных точек, необходимых браузеру для обработки процесса федерации идентификации и управления входами в систему. Конечные точки должны быть одной области с конфигурацией.

Браузер отправляет неуполномоченный запрос на конфигурационный файл с помощью метода GET, который не обрабатывает перенаправления. Это эффективно предотвращает получение IdP информации о том, кто инициировал запрос и какой RP пытается подключиться.

Конфигурационный файл (размещенный по адресу https://accounts.idp.example/config.json в нашем примере) должен иметь следующую структуру JSON:

{
  "accounts_endpoint": "/accounts.php",
  "client_metadata_endpoint": "/client_metadata.php",
  "id_assertion_endpoint": "/assertion.php",
  "login_url": "/login",
  "branding": {
    "background_color": "green",
    "color": "0xFFEEAA",
    "icons": [
      {
        "url": "https://idp.example/icon.ico",
        "size": 25
      }
    ]
  }
}

Свойства следующие:

accounts_endpoint

URL конечной точки списка учетных записей, возвращающий список учетных записей, с которыми пользователь в данный момент авторизован на IdP. Браузер использует эти данные для создания списка вариантов входа для отображения пользователю в интерфейсе FedCM, предоставляемом браузером.

client_metadata_endpoint Необязательно

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

id_assertion_endpoint

URL конечной точки утверждения идентификации, которая, при отправке действительных учетных данных пользователя, должна ответить токеном валидации, который RP может использовать для проверки аутентификации.

login_url

URL страницы входа для входа пользователя в IdP.

branding Необязательно

Содержит информацию о брендинге, которая будет использоваться в интерфейсе FedCM, предоставляемом браузером, для настройки его внешнего вида по желанию IdP.

Следующая таблица обобщает различные запросы, выполняемые API FedCM:

Конечная точка/ресурс Метод Авторизованный (с куки) Включает Origin
well-known/config.json GET Нет Нет
accounts_endpoint GET Да Нет
client_metadata_endpoint GET Нет Да
id_assertion_endpoint POST Да Да

Примечание: Подробное описание процесса FedCM, в котором выполняются эти запросы, см. в процессе входа FedCM.

Примечание: Ни один из запросов, выполняемых API FedCM к конечным точкам, описанным здесь, не позволяет обрабатывать перенаправления, в целях конфиденциальности.

Конечная точка списка учетных записей

Браузер отправляет авторизованные запросы (т.е. с cookie, идентифицирующей пользователя, авторизованного в системе) на эту конечную точку с помощью метода GET. В запросе отсутствует параметр client_id, заголовок Origin или заголовок Referer. Это эффективно предотвращает получение IdP информации о том, к какому RP пытается войти пользователь. Список возвращаемых учетных записей не зависит от RP.

Например:

GET /accounts.php HTTP/1.1
Host: idp.example
Accept: application/json
Cookie: 0x23223
Sec-Fetch-Dest: webidentity

Ответ на успешный запрос возвращает список всех учетных записей IdP, с которыми пользователь в настоящее время авторизован (не конкретные для любого RP), с структурой JSON, соответствующей следующей:

{
  "accounts": [
    {
      "id": "john_doe",
      "given_name": "John",
      "name": "John Doe",
      "email": "john_doe@idp.example",
      "picture": "https://idp.example/profile/123",
      "approved_clients": ["123", "456", "789"],
      "login_hints": ["john_doe", "john_doe@idp.example"]
    },
    {
      "id": "johnny",
      "given_name": "Johnny",
      "name": "Johnny",
      "email": "johnny@idp.example",
      "picture": "https://idp.example/profile/456",
      "approved_clients": ["abc", "def", "ghi"],
      "login_hints": ["johnny", "johnny@idp.example"]
    }
  ]
}

Включает следующую информацию:

id

Уникальный идентификатор пользователя.

name

Фамилия пользователя.

email

Электронный адрес пользователя.

given_name Необязательно

Имя пользователя.

picture Необязательно

URL-адрес изображения аватара пользователя.

approved_clients Необязательно

Массив RP-клиентов, с которыми пользователь зарегистрирован.

login_hints Необязательно

Массив строк, представляющих учётную запись. Эти строки используются для фильтрации списка вариантов учетных записей, которые браузер предлагает пользователю для входа. Это происходит, когда свойство loginHint задаётся внутри identity.providers в связанном вызове get(). Любая учётная запись со строкой в массиве login_hints, соответствующей предоставленному loginHint, включается.

Примечание: Если пользователь не авторизован ни в одной учётной записи IdP, конечная точка должна ответить кодом HTTP 401 (Неавторизован).

Конечная точка метаданных клиента

Браузер отправляет неуполномоченные запросы на эту конечную точку с помощью метода GET, с clientId, переданным в вызов get() в качестве параметра.

Например:

GET /client_metadata.php?client_id=1234 HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Accept: application/json
Sec-Fetch-Dest: webidentity

Ответ на успешный запрос включает URL-адреса, указывающие на метаданные и страницы пользовательского соглашения RP, которые будут использоваться в интерфейсе FedCM, предоставляемом браузером. Он должен соответствовать структуре JSON, приведенной ниже:

{
  "privacy_policy_url": "https://rp.example/privacy_policy.html",
  "terms_of_service_url": "https://rp.example/terms_of_service.html"
}

Конечная точка утверждения идентификации

Браузер отправляет запросы с учётными данными на этот конечный пункт с помощью метода POST, с типом контента application/x-www-form-urlencoded. В запросе также содержится полезная нагрузка, включающая подробности о попытке входа в систему и учетной записи, подлежащей валидации.

Он должен выглядеть примерно так:

POST /assertion.php HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
account_id=123&client_id=client1234&nonce=Ct60bD&disclosure_text_shown=true&is_auto_selected=true

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

{
  "token": "***********"
}

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

client_id

Идентификатор клиента RP (который соответствует clientId из исходного запроса get()).

account_id

Уникальный идентификатор учётной записи пользователя, подлежащей входу в систему (который соответствует идентификатору пользователя id из ответа конечного пункта списка учётных записей).

nonce Необязательно

Номера запроса, предоставленные RP.

disclosure_text_shown

Строка "true" или "false" , указывающая, отображался ли текст раскрытия или нет. Текст раскрытия — это информация, отображаемая пользователю (включая ссылки на условия использования и политику конфиденциальности, если они предоставлены), если пользователь вошел в IdP, но не имеет учётной записи конкретно в текущем RP (в этом случае ему нужно выбрать «Продолжить как...» свою личность IdP и затем создать соответствующую учётную запись в RP).

is_auto_selected

Строка "true" или "false" , указывающая, был ли запрос на валидацию аутентификации инициирован в результате автоматической повторной аутентификации, т. е. без участия пользователя. Это может произойти, когда вызов get() выполняется с значением параметра mediation равным "optional" или "silent". Для IdP важно знать, произошла ли автоматическая повторная аутентификация для оценки производительности и в случае необходимости повышенной безопасности. Например, IdP может вернуть код ошибки, сообщая RP, что требуется явное участие пользователя (mediation="required").

Примечание: Если вызов get() успешно выполняется, значение is_auto_selected также передаётся RP через свойство IdentityCredential.isAutoSelected.

Ответы с ошибками подтверждения идентификации

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

{
  "error": {
    "code": "access_denied",
    "url": "https://idp.example/error?type=access_denied"
  }
}

Поля ответа с ошибкой следующие:

code Необязательно

Строка. Это может быть известная ошибка из списка ошибок OAuth 2.0 или произвольная строка.

url Необязательно

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

Эта информация может быть использована несколькими способами:

  • Браузер может отобразить пользователю специальный интерфейс, информируя его о том, что пошло не так (см. документацию Chrome для примера). Имейте в виду, что если запрос не удалось выполнить из-за недоступности сервера IdP, он, очевидно, не может вернуть никакой информации. В таких случаях браузер сообщит об этом с помощью универсального сообщения.
  • Соответствующий вызов RP navigator.credentials.get(), используемый для попытки входа в систему, отклонит своё обещание с IdentityCredentialError, содержащим информацию об ошибке. RP может перехватить эту ошибку и дополнить пользовательский интерфейс браузера некоторой информацией, помогающей пользователю в будущих попытках входа в систему.

Обновление состояния входа в систему с помощью API состояния входа в систему

API состояния входа в систему позволяет IdP информировать браузер о своём состоянии входа в систему (входа) в этом конкретном браузере — другими словами, «есть ли какие-либо пользователи, авторизованные в IdP в текущем браузере или нет». Браузер сохраняет это состояние для каждого IdP; API FedCM затем использует его для сокращения количества запросов, отправляемых IdP (так как ему не нужно тратить время на запрос учётных записей, когда пользователи не авторизованы в IdP). Это также смягчает возможные атаки на основе временных данных.

Для каждого известного IdP (определяемого его URL-адресом конфигурации) браузер сохраняет переменную со тремя состояниями, представляющую состояние входа в систему с тремя возможными значениями:

  • "logged-in": IdP имеет по крайней мере одну учётную запись пользователя, авторизованную. Обратите внимание, что на данном этапе RP и браузер не знают, какой это пользователь. Информация о конкретных пользователях возвращается из конечного пункта accounts_endpoint IdP на более позднем этапе процесса FedCM.
  • "logged-out": Все учётные записи IdP в настоящее время выведены из системы.
  • "unknown": Состояние входа в систему этого IdP неизвестно. Это значение по умолчанию.

Установка состояния входа в систему

IdP должен обновлять своё состояние входа в систему, когда пользователь входит в IdP или выходит из него. Это можно сделать двумя способами:

  • Заголовок ответа HTTP Set-Login можно установить в запросе навигации верхнего уровня или в запросе к ресурсу в том же домене:

    Set-Login: logged-in
    
    Set-Login: logged-out
    
  • Метод Navigator.login.setStatus() можно вызвать из происхождения IdP:

    /* Set logged-in status */
    navigator.login.setStatus("logged-in");
    
    /* Set logged-out status */
    navigator.login.setStatus("logged-out");
    

Как состояние входа в систему влияет на процесс федеративного входа в систему

Когда RP пытается выполнить федеративный вход в систему, проверяется состояние входа в систему:

  • Если состояние входа в систему равно "logged-in", осуществляется запрос к конечному пункту IdP списка учётных записей, и доступные учётные записи для входа в систему отображаются пользователю в диалоговом окне FedCM, предоставляемом браузером.
  • Если состояние входа в систему равно "logged-out", обещание, возвращаемое запросом FedCM get(), отклоняется без отправки запроса к конечному пункту списка учётных записей. В таком случае разработчик должен обработать поток, например, предложив пользователю войти в подходящий IdP.
  • Если состояние входа в систему равно "unknown", осуществляется запрос к конечному пункту IdP списка учётных записей, и состояние входа в систему обновляется в зависимости от ответа:
    • Если конечный пункт возвращает список доступных учётных записей для входа в систему, обновите статус на "logged-in" и отобразите варианты входа в систему пользователю в диалоговом окне FedCM, предоставляемом браузером.
    • Если конечный пункт не возвращает учётных записей, обновите статус на "logged-out"; обещание, возвращаемое запросом FedCM get(), затем отклоняется.

Что делать, если состояние входа в систему браузера и IdP становятся несинхронизированными?

Несмотря на то, что API состояния входа в систему информирует браузер о состоянии входа в систему IdP, браузер и IdP могут выйти из синхронизации. Например, сеансы IdP могут истекать, что означает, что все учётные записи пользователей выходят из системы, но состояние входа в систему всё ещё установлено на "logged-in" (приложение не смогло установить состояние входа в систему на "logged-out"). В таком случае при попытке федеративного входа в систему будет отправлен запрос к конечному пункту IdP списка учётных записей, но доступных учётных записей не будет возвращено, потому что сеанс больше недоступен.

В этом случае браузер может динамически позволить пользователю войти в IdP, открыв страницу входа IdP в диалоговом окне (URL-адрес входа находится в файле конфигурации IdP login_url). Точная структура этого потока зависит от браузера; например, Chrome обрабатывает это таким образом.

После входа пользователя в IdP IdP должен:

  • Сообщить браузеру об авторизации пользователя, установив состояние входа в систему на "logged-in".
  • Закрыть диалоговое окно входа, вызвав метод IdentityProvider.close().

См. также

  • Federated Credential Management API на developers.google.com (2023)

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API/IDP_integration

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API