# 联合凭据管理（FedCM）

> 说明依赖方如何通过 FedCM 请求 IdentityCredential、检测支持情况、处理策略与请求失败，并保留回退登录路径。

联合凭据管理 API 让依赖方请求浏览器居中协调身份提供方的登录。依赖方使用 `identity` 请求调用 `navigator.credentials.get()`；请求成功后返回携带提供方令牌的 `IdentityCredential`（[FedCM API](https://www.w3.org/TR/fedcm/)，W3C）。

## 支持情况

BCD 记录 `IdentityCredential` 从 Chrome 108 起得到支持，并把支持情况镜像到 Android 版 Chrome、Edge、Opera、Samsung Internet 和 Meta Quest Browser。

Firefox、Safari 和 Android WebView 记为不支持，因此 FedCM 尚未达到 Baseline（BCD `api.IdentityCredential`；[FedCM API](https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API)，MDN）。

## 语法

```js
const credential = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/fedcm.json',
      clientId: 'rp-client-id',
    }],
  },
});
```

浏览器获取提供方配置及相关身份提供方端点，协调其账户界面，并把凭据返回给依赖方。FedCM 是安全上下文 API，通过凭据管理 API 暴露在 `Window` 上。

## 参数

`identity.providers` 是提供方配置序列。W3C 示例使用的核心字段是 `configURL` 和 `clientId`：前者标识提供方配置，后者向该提供方标识依赖方。按照规范，请求还可以携带 `nonce`、`loginHint` 和 `domainHint` 等值。

返回的 `IdentityCredential` 带有身份提供方给出的 `token`。规范定义 `isAutoSelected`，用于报告浏览器在界面流程中是否自动选择了凭据。

## 异常

- 被 `identity-credentials-get` 权限策略阻止的文档会得到以 `NotAllowedError` 拒绝的 Promise。该特性的默认允许列表是 `self`；跨源 iframe 需要显式设置 `allow="identity-credentials-get"`（[Permissions Policy integration](https://www.w3.org/TR/fedcm/#permissions-policy-integration)，W3C）。
- 规范把提供方请求失败和没有符合条件的账户映射为 `NetworkError`。`identity-credentials-get` 策略拦截请求时返回 `NotAllowedError`，`configURL` 无效时返回 `InvalidStateError`（[Create an IdentityCredential](https://www.w3.org/TR/fedcm/#create-an-identitycredential)，W3C）。
- FedCM 需要身份提供方配合，依赖方无法独立部署。不支持 FedCM 时，下面的示例会显示网站现有登录路由。

:::caution
并发 FedCM 请求在 Chromium 中以 `NotAllowedError: Only one navigator.credentials.get request may be outstanding at one time.` 拒绝。这个确切字符串定义在 Chromium 的 [`authentication_credentials_container.cc`](https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc) 中（chromium.googlesource.com）。
:::

## 示例

下面的示例从登录按钮启动 FedCM，并保留普通链接作为回退。

### 请求凭据并提供回退

同时检测凭据管理容器和 `IdentityCredential`。任一对象不存在，或居中协调的请求没有返回令牌时，继续使用网站已有的登录路由。

```html
<button id="federated-sign-in" type="button">使用身份提供方登录</button>
<a id="sign-in-fallback" href="/sign-in" hidden>使用标准登录页</a>
<p id="sign-in-status" role="status"></p>

<script type="module">
const button = document.querySelector('#federated-sign-in');
const fallback = document.querySelector('#sign-in-fallback');
const status = document.querySelector('#sign-in-status');

function useFallback(message) {
  status.textContent = message;
  fallback.hidden = false;
}

async function sendTokenToServer(token) {
  const response = await fetch('/session/fedcm', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token }),
  });
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
}

async function signIn() {
  if (!('credentials' in navigator) || !('IdentityCredential' in window)) {
    useFallback('FedCM 不可用，请使用标准登录页。');
    return;
  }

  try {
    const credential = await navigator.credentials.get({
      identity: {
        providers: [{
          configURL: 'https://idp.example/fedcm.json',
          clientId: 'rp-client-id',
        }],
      },
    });

    if (!credential?.token) {
      useFallback('未返回凭据，请使用标准登录页。');
      return;
    }
    await sendTokenToServer(credential.token);
    status.textContent = '凭据已发送到服务器。';
  } catch (error) {
    useFallback(`FedCM 未完成：${error.name}`);
  }
}

button.addEventListener('click', signIn);
</script>
```

示例定义了所引用的全部元素和辅助函数。请把提供方配置、客户端 ID、回退 URL 和 `/session/fedcm` 端点替换为依赖方及身份提供方的实际值。把不透明令牌发送到依赖方服务器验证。不要把 `IdentityCredential` 存在视为某个提供方已经配置好或请求必然成功的证明。

### 保持回退入口可用

不支持 FedCM、没有返回令牌或请求被拒绝时，代码都会调用 `useFallback()`，显示示例中的普通 `/sign-in` 链接。

## 另请参阅

- [凭据管理 API](/zh/reference/capabilities/credential-management/)
- [WebAuthn 与通行密钥](/zh/reference/capabilities/webauthn-passkeys/)
- [Storage Access API](/zh/reference/storage/storage-access-api/)
- [Federated Credential Management API](https://www.w3.org/TR/fedcm/)（w3.org）
- [Federated Credential Management API](https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API)（MDN）