Внедрение решения для идентификации с помощью FedCM на стороне поставщика удостоверений.

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

Для внедрения FedCM поставщики удостоверений должны выполнить следующие шаги:

Создать известный файл

Чтобы предотвратить злоупотребление API трекерами , общеизвестный файл должен быть передан из /.well-known/web-identity eTLD+1 IdP.

Известный файл может включать в себя следующие свойства:

Свойство Необходимый Описание
provider_urls необходимый Массив путей к файлам конфигурации IdP. Игнорируется (но все равно требуется), если указаны accounts_endpoint и login_url .
accounts_endpoint рекомендуется, требуется login_url
URL-адрес конечной точки учетной записи. Это позволяет поддерживать несколько конфигураций, при условии, что каждый файл конфигурации использует один и тот же URL-адрес login_url и accounts_endpoint .

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

Примечание. Этот параметр поддерживается начиная с Chrome 132 и более поздних версий.

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

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

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

  • IdP должен поддерживать несколько различных тестовых и рабочих конфигураций.
  • IdP должен поддерживать разные конфигурации для каждого региона (например, eu-idp.example и us-idp.example ).

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

  {
    // This property is required, but will be ignored when IdP supports
    // multiple configs (when `accounts_endpoint` and `login_url` are
    // specified), as long as `accounts_endpoint` and `login_url` in
    // that config file match those in the well-known file.
    "provider_urls": [ "https://idp.example/fedcm.json" ],

    // Specify accounts_endpoint and login_url properties to support
    // multiple config files.
    // Note: The accounts_endpoint and login_url must be identical
    // across all config files. Otherwise,
    // the configurations won't be supported.
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }

Создайте файл конфигурации 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;

RP передаст URL-адрес файла конфигурации вызову API FedCM , чтобы пользователь мог войти в систему:

  // Executed on RP's side:
  const credential = await navigator.credentials.get({
    identity: {
      context: 'signup',
      providers: [{
        // To allow users to sign in with an IdP using FedCM, RP specifies the IdP's config file URL:
        configURL: 'https://accounts.idp.example/fedcm.json',
        clientId: '********',
  });
  const { token } = credential;

Браузер получит файл конфигурации с помощью запроса 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. JSON включает в себя следующие свойства:

Свойство Описание
accounts_endpoint (обязательно) URL-адрес конечной точки учетной записи .
accounts.include (необязательно) Строка пользовательской метки учетной записи, определяющая, какие учетные записи должны быть возвращены при использовании этого файла конфигурации, например: "accounts": {"include": "developer"} .
Поставщик удостоверений может реализовать специальную маркировку учетных записей следующим образом:

Например, поставщик удостоверений реализует файл конфигурации "https://idp.example/developer-config.json" с указанием "accounts": {"include": "developer"} . IdP также помечает некоторые учетные записи меткой "developer" , используя параметр labels в конечной точке учетных записей . Когда RP вызывает navigator.credentials.get() с указанным файлом конфигурации "https://idp.example/developer-config.json" , будут возвращены только учетные записи с меткой "developer" .

Примечание. Пользовательские метки учетных записей поддерживаются начиная с Chrome 132.
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 пикселей в пассивном режиме и больше или равно 40 пикселей в активном режиме.
modes Объект, содержащий спецификации того, как пользовательский интерфейс FedCM будет отображаться в различных режимах:
  • active
  • passive
modes.active Объект, содержащий свойства, позволяющие настраивать поведение FedCM в определенном режиме. Оба modes.active и modes.passive могут содержать следующий параметр:
  • supports_use_other_account : логическое значение, указывающее, может ли пользователь войти в систему с учетной записью, отличной от той, с которой он в настоящее время вошел в систему (если IdP поддерживает несколько учетных записей).

Примечание. Функция «Использовать другую учетную запись» и активный режим поддерживаются в Chrome 132.
modes.passive

Вот пример тела ответа от IdP:

  {
    "accounts_endpoint": "/accounts.example",
    "client_metadata_endpoint": "/client_metadata.example",
    "id_assertion_endpoint": "/assertion.example",
    "disconnect_endpoint": "/disconnect.example",
    "login_url": "/login",
    // When RPs use this config file, only those accounts will be
    //returned that include `developer` label in the accounts endpoint.
    "accounts": {"include": "developer"},
    "modes": {
        "active": {
          "supports_use_other_account": true,
        }
    },
    "branding": {
      "background_color": "green",
      "color": "#FFEEAA",
      "icons": [{
        "url": "https://idp.example/icon.ico",
        "size": 25
      }]
    }
  }

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

Конечные точки поставщика удостоверений
Конечные точки поставщика удостоверений

Использовать другую учетную запись

Пользователи могут переключиться на учетную запись, отличную от той, под которой они в данный момент вошли в систему, если поставщик удостоверений поддерживает несколько учетных записей или заменяет существующую учетную запись.

Чтобы позволить пользователю выбирать другие учетные записи, IdP должен указать эту функцию в файле конфигурации :

  {
    "accounts_endpoint" : "/accounts.example",
    "modes": {
      "active": {
        // Allow the user to choose other account (false by default)
        "supports_use_other_account": true
      }
      // "passive" mode can be configured separately
    }
  }

Конечная точка аккаунтов

Конечная точка учетных записей IdP возвращает список учетных записей, в которые пользователь вошел в IdP. Если поставщик удостоверений поддерживает несколько учетных записей, эта конечная точка вернет все зарегистрированные учетные записи.

Браузер отправляет запрос GET с файлами cookie с SameSite=None , но без параметра client_id , заголовка Origin или заголовка Referer . Это эффективно не позволяет IdP узнать, на какую RP пользователь пытается войти. Например:

  GET /accounts.example 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 для фильтрации учетных записей.
labels (по желанию) Массив строковых меток пользовательских учетных записей, с которыми связана учетная запись.
Поставщик удостоверений может реализовать специальную маркировку учетных записей следующим образом:
  • Укажите метки учетных записей в конечной точке учетных записей (используя этот параметр labels ).
  • Создайте файл конфигурации для каждой конкретной метки.

Например, поставщик удостоверений реализует файл конфигурации https://idp.example/developer-config.json с указанием "accounts": {"include": "developer"} . IdP также помечает некоторые учетные записи меткой "developer" , используя параметр labels в конечной точке учетных записей . Когда RP вызывает navigator.credentials.get() с указанным конфигурационным файлом https://idp.example/developer-config.json , будут возвращены только учетные записи с меткой "developer" .

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

Примечание. Пользовательские метки учетных записей поддерживаются начиная с Chrome 132.

Пример тела ответа:

  {
    "accounts": [{
      "id": "1234",
      "given_name": "John",
      "name": "John Doe",
      "email": "john_doe@idp.example",
      "picture": "https://idp.example/profile/123",
      // Ids of those RPs where this account can be used
      "approved_clients": ["123", "456", "789"],
      // This account has 'login_hints`. When an RP calls `navigator.credentials.get()`
      // with a `loginHint` value specified, for example, `exampleHint`, only those
      // accounts will be shown to the user whose 'login_hints' array contains the `exampleHint`.
      "login_hints": ["demo1", "exampleHint"],
      // This account is labelled. IdP can implement a specific config file for a
      // label, for example, `https://idp.example/developer-config.json`. Like that
      // RPs can filter out accounts by calling `navigator.credentials.get()` with
      // `https://idp.example/developer-config.json` config file.
      "labels": ["hr", "developer"]
    }, {
      "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"],
      "domain_hints": ["@domain.example"]
    }]
  }

Если пользователь не вошел в систему, ответьте HTTP 401 (неавторизованный).

Возвращенный список учетных записей используется браузером и не будет доступен RP.

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

Конечная точка утверждения идентификатора IdP возвращает утверждение для вошедшего в систему пользователя. Когда пользователь входит на веб-сайт RP с помощью вызова navigator.credentials.get() , браузер отправляет POST запрос с файлами cookie с SameSite=None и типом контента application/x-www-form-urlencoded в эту конечную точку с следующую информацию:

Свойство Описание
client_id (обязательно) Идентификатор клиента RP.
account_id (обязательно) Уникальный идентификатор вошедшего пользователя.
disclosure_text_shown Результатом является строка "true" или "false" (а не логическое значение). Результат будет "false" в следующих случаях:
  • Если текст раскрытия не был показан, поскольку идентификатор клиента RP был включен в список свойств approved_clients ответа от конечной точки учетных записей .
  • Если текст раскрытия не был показан, потому что браузер наблюдал момент регистрации в прошлом при отсутствии approved_clients .
  • Если параметр fields не включает одно или несколько из трех полей («имя», «электронная почта» и «изображение»), например, fields=[ ] или fields=['name', 'picture'] . Это необходимо для обратной совместимости со старыми реализациями IdP, которые ожидают, что строка раскрытия всегда будет включать все три поля.
is_auto_selected Если на RP выполняется автоматическая повторная аутентификация , is_auto_selected указывает "true" . В противном случае "false" . Это полезно для поддержки большего количества функций, связанных с безопасностью. Например, некоторые пользователи могут предпочесть более высокий уровень безопасности, который требует явного посредничества пользователя при аутентификации. Если IdP получает запрос токена без такого посредничества, он может обработать запрос по-другому. Например, верните код ошибки, чтобы RP мог снова вызвать API FedCM с помощью mediation: required .
fields (необязательно) Массив строк, определяющий информацию о пользователе («имя», «адрес электронной почты», «изображение»), которой RP должен поделиться с IdP.
Браузер отправит fields disclosure_text_shown и disclosure_shown_for перечисления указанных полей в запросе POST, как в следующем примере .

Примечание. Параметр Fields поддерживается начиная с Chrome 132.
params (необязательно) Любой действительный объект JSON, который позволяет указать дополнительные пользовательские параметры «ключ-значение», например:
  • scope : строковое значение, содержащее дополнительные разрешения, которые необходимо запросить RP, например "drive.readonly calendar.readonly"
  • nonce : случайная строка, предоставляемая RP для обеспечения выдачи ответа на этот конкретный запрос. Предотвращает повторные атаки.
  • Другие пользовательские параметры «ключ-значение».
Когда браузер отправляет запрос POST, значение params будет сериализовано в JSON, а затем закодировано в процентах .

Примечание. API параметров поддерживается Chrome 132 и более поздних версий.

Пример HTTP-заголовка:

  POST /assertion.example HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

  // disclosure_text_shown is set to 'false', as the 'name' field value is missing in 'fields' array
  // params value is serialized to JSON and then percent-encoded.
  account_id=123&client_id=client1234&disclosure_text_shown=false&is_auto_selected=true&params=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&disclosure_text_shown=true&fields=email,picture&disclosure_shown_for=email,picture

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

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

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

Браузер ожидает ответ JSON, который включает следующее свойство:

Свойство Описание
token Токен — это строка, содержащая утверждения об аутентификации.
continue_on URL-адрес перенаправления, который обеспечивает многоэтапный процесс входа.

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

  {
    // IdP can respond with a token to authenticate the user
    "token": "***********"
  }

Продолжить работу над функцией

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

  • Разрешение на доступ к серверным ресурсам пользователя.
  • Проверка актуальности контактной информации.
  • Родительский контроль.

Конечная точка утверждения идентификатора может возвращать свойство continue_on , которое включает абсолютный или относительный путь к конечной точке утверждения идентификатора.

  {
    // In the id_assertion_endpoint, instead of returning a typical
    // "token" response, the IdP decides that it needs the user to
    // continue on a popup window:
    "continue_on": "https://idp.example/continue_on_url"
  }

Если ответ содержит параметр continue_on , открывается новое всплывающее окно, которое направляет пользователя по указанному пути. После взаимодействия пользователя со страницей continue_on поставщик удостоверений должен вызвать IdentityProvider.resolve() с токеном, переданным в качестве аргумента, чтобы можно было выполнить обещание исходного вызова navigator.credentials.get() :

  document.getElementById('example-button').addEventListener('click', async () => {
    let accessToken = await fetch('/generate_access_token.cgi');
    // Closes the window and resolves the promise (that is still hanging
    // in the relying party's renderer) with the value that is passed.
    IdentityProvider.resolve(accessToken);
  });

Затем браузер автоматически закроет всплывающее окно и вернет токен вызывающей стороне API. Одноразовый вызов IdentityProvider.resolve() — единственный способ взаимодействия родительского окна (RP) и всплывающего окна (IdP).
Если пользователь отклоняет запрос, IdP может закрыть окно, вызвав IdentityProvider.close() .

  IdentityProvider.close();

Для работы API продолжения требуется явное взаимодействие с пользователем (клики). Вот как Continuation API работает с различными режимами медиации :

  • В пассивном режиме :
    • mediation: 'optional' (по умолчанию): API продолжения будет работать только с жестом пользователя, например нажатием кнопки на странице или в пользовательском интерфейсе FedCM. Когда автоматическая повторная аутентификация запускается без жеста пользователя, всплывающее окно не открывается и обещание отклоняется.
    • mediation: 'required' : всегда просит пользователя взаимодействовать, поэтому API продолжения всегда работает.
  • В активном режиме :
    • Активация пользователя требуется всегда. API продолжения совместим.

Если по какой-то причине пользователь изменил свою учетную запись во всплывающем окне (например, IdP предлагает функцию «использовать другую учетную запись» или в случаях делегирования), вызов разрешения принимает необязательный второй аргумент, позволяющий что-то вроде:

  IdentityProvider.resolve(token, {accountId: '1234');

Вернуть ответ об ошибке

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"
    }
  }

Пользовательские ярлыки учетной записи

С помощью пользовательских меток учетных записей поставщик удостоверений может помечать учетные записи пользователей метками, а RP может выбирать только учетные записи с определенными метками, указав configURL для этой конкретной метки. Это может быть полезно, когда RP необходимо отфильтровать учетные записи по определенным критериям, например, чтобы отображать только учетные записи для определенных ролей, такие как "developer" или "hr" .

Аналогичная фильтрация возможна с использованием функций « Подсказка домена» и « Подсказка для входа» , указав их в вызове navigator.credentials.get() . Однако пользовательские метки учетной записи могут фильтровать пользователей, указав файл конфигурации, что особенно полезно при использовании нескольких URL-адресов configURL . Пользовательские метки учетной записи также отличаются тем, что они предоставляются с сервера IdP, а не от RP, как подсказки для входа в систему или домена.

Рассмотрим поставщика удостоверений, который хочет различать учетные записи "developer" и "hr" . Для этого IdP должен поддерживать два configURL для "developer" и "hr" соответственно:

  • Файл конфигурации разработчика https://idp.example/developer/fedcm.json имеет метку "developer" , а файл конфигурации предприятия https://idp.example/hr/fedcm.json имеет метку "hr" следующим образом. :
  // The developer config file at `https://idp.example/developer/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "accounts": {
      // Account label
      "include": "developer"
    }
  }
  // The hr config file at `https://idp.example/hr/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "accounts": {
      // Account label
      "include": "hr"
    }
  }
  • При такой настройке известный файл должен включать accounts_endpoint и login_url , чтобы разрешить несколько configURL:
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • Конечная точка общих учетных записей IdP (в этом примере https://idp.example/accounts ) возвращает список учетных записей, который включает свойство labels с назначенными метками в массиве для каждой учетной записи:
  {
  "accounts": [{
    "id": "123",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "labels": ["developer"]
    }], [{
    "id": "4567",
    "given_name": "Jane",
    "name": "Jane Doe",
    "email": "jane_doe@idp.example",
    "picture": "https://idp.example/profile/4567",
    "labels": ["hr"]
    }]
  }

Если RP хочет разрешить пользователям "hr" входить в систему, они могут указать configURL https://idp.example/hr/fedcm.json в вызове navigator.credentials.get() :

  let { token } = await navigator.credentials.get({
    identity: {
      providers: [{
        clientId: '1234',
        nonce: '234234',
        configURL: 'https://idp.example/hr/fedcm.json',
      },
    }
  });

В результате пользователю для входа доступен только идентификатор учетной записи 4567 Идентификатор учетной записи 123 незаметно скрывается браузером, поэтому пользователю не будет предоставлена ​​​​учетная запись, которая не поддерживается IdP в этом случае. сайт.

  • Метки представляют собой строки. Если массив labels или поле include содержит что-то, не являющееся строкой, оно игнорируется.
  • Если в configURL не указаны метки, все учетные записи будут отображаться в средстве выбора учетной записи FedCM.
  • Если для учетной записи не указаны метки, она будет отображаться в средстве выбора учетной записи только в том случае, если configURL также не указана метка.
  • Если ни одна учетная запись не соответствует запрошенной метке в пассивном режиме (аналогично функции подсказки домена), в диалоговом окне FedCM отображается приглашение для входа в систему, которое позволяет пользователю войти в учетную запись IdP. В активном режиме всплывающее окно входа открывается напрямую.

Отключить конечную точку

Вызывая IdentityCredential.disconnect() , браузер отправляет POST запрос между источниками с файлами cookie с SameSite=None и типом контента application/x-www-form-urlencoded в эту конечную точку отключения со следующей информацией:

Свойство Описание
account_hint Подсказка для учетной записи IdP..
client_id Идентификатор клиента RP.
  POST /disconnect.example 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 (совместное использование ресурсов между источниками) .
  2. Убедитесь, что запрос содержит HTTP-заголовок Sec-Fetch-Dest: webidentity .
  3. Сопоставьте заголовок Origin с источником RP, определенным client_id . Отклонить, если они не совпадают.
  4. Сопоставьте account_hint с идентификаторами уже вошедших в систему учетных записей.
  5. Отключите учетную запись пользователя от RP.
  6. Ответьте браузеру, указав идентифицированную информацию об учетной записи пользователя в формате JSON.

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

  {
    "account_id": "account456"
  }

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

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

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

Браузер отправляет запрос GET , используя client_id navigator.credentials.get без файлов cookie. Например:

  GET /client_metadata.example?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.
icons (по желанию) Массив объектов, например [{ "url": "https://rp.example/rp-icon.ico", "size": 40}]

Браузер ожидает ответа JSON от конечной точки:

  {
    "privacy_policy_url": "https://rp.example/privacy_policy.html",
    "terms_of_service_url": "https://rp.example/terms_of_service.html",
    "icons": [{
          "url": "https://rp.example/rp-icon.ico",
          "size": 40
      }]
  }

Возвращенные метаданные клиента используются браузером и не будут доступны RP.

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

Эта конечная точка используется, чтобы позволить пользователю войти в IdP.

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

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

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

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

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

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

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

Информировать браузер о статусе входа пользователя

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

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

  • logged-in
  • logged-out
  • unknown (по умолчанию)
Состояние входа Описание
logged-in Когда для статуса входа пользователя установлено logged-in , RP, вызывающая FedCM, отправляет запросы к конечной точке учетных записей IdP и отображает доступные учетные записи пользователю в диалоговом окне FedCM.
logged-out Когда статус входа пользователя logged-out , вызов FedCM автоматически завершается неудачей без выполнения запроса к конечной точке учетных записей IdP.
unknown (по умолчанию) unknown статус устанавливается до того, как поставщик удостоверений отправит сигнал с помощью API статуса входа. Если статус unknown , браузер отправляет запрос к конечной точке учетных записей IdP и обновляет статус на основе ответа от конечной точки учетных записей.

Чтобы сигнализировать о том, что пользователь вошел в систему, отправьте HTTP-заголовок Set-Login: logged-in в навигации верхнего уровня или запрос подресурса того же сайта в источнике IdP:

  Set-Login: logged-in

Альтернативно, вызовите метод JavaScript navigator.login.setStatus('logged-in') из источника IdP в навигации верхнего уровня:

  navigator.login.setStatus('logged-in')

Статус входа пользователя будет установлен как logged-in .

Чтобы сигнализировать о том, что пользователь вышел из всех своих учетных записей, отправьте 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 .

unknown статус устанавливается до того, как поставщик удостоверений отправит сигнал с помощью API статуса входа. Браузер отправляет запрос к конечной точке учетных записей IdP и обновляет статус на основе ответа от конечной точки учетных записей:

  • Если конечная точка возвращает список активных учетных записей, обновите статус до logged-in ​​и откройте диалоговое окно FedCM, чтобы отобразить эти учетные записи.
  • Если конечная точка не возвращает учетных записей, обновите статус до logged-out и откажитесь от вызова FedCM.

Разрешить пользователю войти в систему с помощью динамического процесса входа.

Несмотря на то, что IdP продолжает сообщать браузеру статус входа пользователя, он может быть не синхронизирован, например, по истечении срока действия сеанса. Браузер пытается отправить запрос с учетными данными в конечную точку учетных записей, когда статус входа logged-in , но сервер не возвращает учетные записи, поскольку сеанс больше не доступен. В таком случае браузер может динамически разрешить пользователю войти в IdP через всплывающее окно .

Следующие шаги

Внедрите FedCM для своих RP и распространяйте JavaScript SDK. Поддерживайте актуальность RP, устраняя необходимость самостоятельной реализации.
Узнайте, как настроить среду и отладить реализацию.