Chrome 116 随附了 FedCM 功能,例如登录提示 API、用户信息 API 和 RP 上下文 API,并针对 IdP 登录状态 API 启动了源试用。
在 Chrome 116 中,Chrome 推出了以下三项新的联合凭据管理 (FedCM) 功能:
- Login Hint API:指定要登录的首选用户账号。
- User Info API:提取回访用户的信息,以便身份提供方 (IdP) 可以在 iframe 内呈现个性化的登录按钮。
- RP Context API:在 FedCM 对话框中使用不同于“登录”的标题。
此外,Chrome 正在针对 IdP 登录状态 API 启动源试用。IdP 登录状态 API 是必需的,并且在发布时会造成重大变更。如果您已实现 FedCM,请务必参与源试用。
登录提示 API
当 FedCM 被调用时,浏览器会显示来自指定身份提供方 (IdP) 的已登录账号。如果 IdP 支持多个账号,则会列出所有已登录的账号。

用户登录后,信赖方 (RP) 有时会要求用户重新进行身份验证。但用户可能不确定自己一直在使用哪个账号。 如果 RP 可以指定要登录的账号,用户将更轻松地选择账号。登录提示将在 Chrome 116 中发布,借助该功能,RP 可以将列表缩小到仅剩一个。
此扩展程序会在 IdP 的 accounts list endpoint 响应中添加一个 login_hints
数组,其中包含 IdP 支持的所有可能的过滤条件类型。例如,如果 IdP 支持按电子邮件地址和 ID 进行过滤,则账号响应可能如下所示:
{
"accounts": [{
"id": "demo1",
"email": "demo1@example.com",
"name": "John Doe",
"login_hints": ["demo1", "demo1@example.com"],
...
}, {
"id": "demo2",
"email": "demo2@example.com",
"name": "Jane Doe",
"login_hints": ["demo2", "demo2@example.com"],
...
}, ...]
}
通过在账号列表中传递 login_hints
,RP 可以使用 loginHint
属性调用 navigator.credentials.get()
,如以下代码示例所示,以选择性地显示指定账号:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "123",
nonce: nonce,
loginHint : "demo1@example.com"
}]
}
});
User Info API
现在,带有 IdP 徽标的登录按钮非常常见,用户可以通过身份联合登录。不过,使用用户的个人资料图标及其信息来装饰按钮,可让用户更直观地进行登录,尤其是当用户之前已使用 IdP 在此网站上注册时。


问题在于,个性化按钮依赖于 iframe 内 IdP 网域上的第三方 Cookie 来识别已登录的用户,以便呈现该按钮,因此一旦第三方 Cookie 被弃用,该按钮将无法使用。
Chrome 116 中提供的 User Info API 可让 IdP 从服务器获取回访用户的信息,而无需依赖第三方 Cookie。
该 API 应由 IdP 从嵌入在 RP 网站上的 iframe 中调用,以便检索用户信息并呈现个性化按钮,就像它是 RP 界面的一部分一样。通过 API 调用,浏览器会向账号列表端点发出请求,然后返回一个用户信息数组,前提是:
- 用户之前已在同一浏览器实例中通过 FedCM 使用 IdP 登录 RP,并且数据尚未清除。
- 用户已在同一浏览器实例中登录 IdP。
// Iframe displaying a page from the https://idp.example origin
const user_info = await IdentityProvider.getUserInfo({
configUrl: "https://idp.example/fedcm.json",
clientId: "client1234"
});
// IdentityProvider.getUserInfo returns an array of user information.
if (user_info.length > 0) {
// Chrome puts returning accounts first, so the first account received is guaranteed to be a returning account.
const name = user_info[0].name;
const given_name = user_info[0].given_name;
const display_name = given_name ? given_name : name;
const picture = user_info[0].picture;
const email = user_info[0].email;
// Renders the personalized sign-in button with the information above.
}
请注意,如需允许从与 IdP 同源的 iframe 内调用 IdentityProvider.getUserInfo()
,嵌入 HTML 必须通过 identity-credentials-get
permissions policy 明确允许这样做。
<iframe src="https://fedcm-demo-idp.dev" allow="identity-credentials-get"></iframe>
您可以在 https://fedcm-demo-rp.dev/active-mode 中查看实际运行情况。
RP Context API
RP Context API 在 Chrome 116 中发布,允许 RP 修改 FedCM 对话框界面中的字符串,以便适应预定义的身份验证上下文。请参阅以下屏幕截图,了解不同选项:




用法很简单;为 identity.context
属性提供 "signin"
(默认值)、"signup"
、"use"
或 "continue"
之一。
const credential = await navigator.credentials.get({
identity: {
// "signin" is the default, "signup", "use" and "continue"
// can also be used
context: "signup",
providers: [{
configURL: "https://idp.example/fedcm.json",
clientId: "1234",
}],
}
});
IdP 登录状态 API 源试用
Chrome 从 116 版开始在桌面设备上启动 IdP 登录状态 API 源试用,随后在 Android Chrome 上启动。源试用可让您使用新功能或实验性功能来构建功能,供用户在这些功能向所有人开放之前限时试用。
IdP 登录状态 API 是一种机制,通过该机制,IdP 可以将用户在 IdP 上的登录状态告知浏览器。借助此 API,浏览器可以减少向 IdP 发出的不必要请求,并缓解潜在的时序攻击。
将用户的登录状态告知浏览器
当用户登录 IdP 或从所有 IdP 账号中退出登录时,IdP 可以通过发送 HTTP 标头或调用 JavaScript API 向浏览器发送用户登录状态信号。浏览器会将状态记录为以下值之一:“sign-in”“sign-out”或“unknown”(默认)。
如需表明用户已登录,请在顶级导航或同源子资源请求中发送 IdP-SignIn-Status: action=signin
HTTP 标头:
IdP-SignIn-Status: action=signin
或者,从 IdP 源调用 JavaScript API IdentityProvider.login()
:
IdentityProvider.login()
这些事件会将用户的登录状态记录为“登录”。当用户的登录状态设置为“登录”时,调用 FedCM 的 PR 会向 IdP 的账号列表端点发出请求,并在 FedCM 对话框中向用户显示可用的账号。
如需表明用户已退出登录其所有账号,请在顶级导航或同源子资源请求中发送 IdP-SignIn-Status: action=signout-all
HTTP 标头:
IdP-SignIn-Status: action=signout-all
或者,从 IdP 源调用 JavaScript API IdentityProvider.logout()
:
IdentityProvider.logout()
这些代码会将用户的登录状态记录为“已退出”。当用户的登录状态为“已退出”时,调用 FedCM 会静默失败,而不会向 IdP 的账号列表端点发出请求。
默认情况下,IdP 登录状态设置为“未知”。此状态在 IdP 使用 IdP 登录状态 API 发送信号之前使用。我们引入此状态是为了更好地进行过渡,因为在发布此 API 时,用户可能已经登录到 IdP,并且在首次调用 FedCM 时,IdP 可能没有机会向浏览器发出此信号。在这种情况下,我们会向 IdP 的账号列表端点发出请求,并根据账号列表端点的响应更新状态:
- 如果端点返回活跃账号列表,请将状态更新为“登录”,并打开 FedCM 对话框以显示这些账号。
- 如果端点未返回任何账号,请将状态更新为“退出”,并使 FedCM 调用失败。
如果用户会话过期,会发生什么情况?允许用户通过动态登录流程登录
即使 IdP 继续向浏览器告知用户的登录状态,该状态也可能不同步,例如在会话过期时。当登录状态为“已登录”时,浏览器会尝试向账号列表端点发送包含凭据的请求,但服务器会因会话不再可用而拒绝该请求。在这种情况下,浏览器可以通过弹出式窗口动态让用户登录 IdP。
FedCM 对话框会显示一条消息,如下图所示:

点击继续按钮后,浏览器会打开一个弹出式窗口,将用户发送到 IdP 的登录页面。

登录页面网址(必须是 IdP 的来源)可以使用 signin_url
指定,作为 IdP 配置文件的一部分。
{
"accounts_endpoint": "/auth/accounts",
"client_metadata_endpoint": "/auth/metadata",
"id_assertion_endpoint": "/auth/idtokens",
"signin_url": "/signin"
}
}
弹出式窗口是使用第一方 Cookie 的常规浏览器窗口。内容窗口中发生的一切都由 IdP 决定,但没有窗口句柄可用于向 RP 页面发出跨源通信请求。用户登录后,IdP 应执行以下操作:
- 发送
IdP-SignIn-Status: action=signin
标头或调用IdentityProvider.login()
API,以告知浏览器用户已登录。 - 调用
IdentityProvider.close()
以关闭自身(弹出式窗口)。
// User is signed in...
// Don't forget feature detection.
if (IdentityProvider) {
// Signal to the browser that the user has signed in.
IdentityProvider.close();
}
您可以在我们的演示中尝试 IdP 登录状态 API 行为。在您登录演示 IdP 后,会话将在 3 分钟后过期。然后,您可以通过弹出式窗口行为观察到向 IdP 的登录。
参与源试用
您可以在 Chrome 116 或更高版本中启用 Chrome
flag
chrome://flags#fedcm-idp-signin-status-api
,在本地试用 IdP 登录状态 API。
您还可以通过注册两次源试用,启用 IdP 登录状态 API:
通过源试用,您可以试用新功能,并向 Web 标准社区反馈这些功能的实用性、可行性和有效性。如需了解详情,请参阅面向 Web 开发者的 Origin 试用指南。
IdP Sign-In Status API 源试用从 Chrome 116 开始,到 Chrome 119 结束。
为 IdP 注册源试用
- 前往源试用注册页面。
- 点击注册按钮,然后填写表单以申请令牌。
- 以 Web Origin 形式输入 IdP 的来源。
- 点击提交。
- 向使用
IdentityProvider.close()
的网页的头部添加origin-trial
<meta>
标记。例如,这可能类似于:
<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
。
为 RP 注册第三方源试用
- 前往源试用注册页面。
- 点击注册按钮,然后填写表单以申请令牌。
- 以 Web Origin 形式输入 IdP 的来源。
- 选中第三方匹配,以使用 JavaScript 在其他来源中注入令牌。
- 点击提交。
- 在第三方网站上嵌入已签发的令牌。
如需将令牌嵌入到第三方网站中,请将以下代码添加到从 IdP 的来源提供的 JavaScript 库或 SDK 中。
const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);
将 TOKEN_GOES_HERE
替换为您自己的令牌。
互动和分享反馈
如果您在测试期间有任何反馈或遇到任何问题,可以在 crbug.com 上分享。
照片由 Dan Cristian Pădureț 拍摄,选自 Unsplash 网站