了解如何使用 FedCM 实现可保护隐私的身份联合。
FedCM(联邦身份凭据管理)是一种可保护隐私的联邦身份服务(例如“使用...账号登录”)方法,用户无需与身份服务或网站分享个人信息即可登录网站。
如需详细了解 FedCM 使用场景、用户体验流程和 API 路线图,请参阅 FedCM API 简介。
FedCM 开发环境
您需要在 Chrome 中的 IdP 和 RP 上都设置安全上下文(HTTPS 或 localhost),才能使用 FedCM。
在 Android 设备上的 Chrome 中调试代码
在本地设置并运行服务器,以调试 FedCM 代码。您可以在使用 USB 线连接且支持端口转发的 Android 设备上,在 Chrome 中访问此服务器。
您可以按照远程调试 Android 设备中的说明,使用桌面版开发者工具调试 Android 设备上的 Chrome。
在 Chrome 中阻止第三方 Cookie
在实际强制执行 FedCM 之前,您可以在 Chrome 上测试 FedCM 在没有第三方 Cookie 的情况下如何运作。
如需屏蔽第三方 Cookie,请使用无痕模式,或在桌面设备的设置中选择 chrome://settings/cookies
下的“屏蔽第三方 Cookie”,或在移动设备上依次选择设置 > 网站设置 > Cookie。
使用 FedCM API
如需与 FedCM 集成,您可以为账号列表创建已知文件、配置文件和端点、断言发出,还可以选择创建客户端元数据。
然后,FedCM 会公开 JavaScript API,供 RP 使用这些 API 与 IdP 进行登录。
创建 well-known 文件
为防止跟踪器滥用 API,必须从 IdP 的 eTLD+1 的 /.well-known/web-identity
中提供 well-known 文件。
例如,如果 IdP 端点在 https://accounts.idp.example/
下提供,则必须在 https://idp.example/.well-known/web-identity
下提供 well-known 文件以及 IdP 配置文件。下面是一个众所周知的文件内容示例:
{
"provider_urls": ["https://accounts.idp.example/config.json"]
}
JSON 文件必须包含 provider_urls
属性,其中包含一个 IdP 配置文件网址数组,该数组可由 RP 指定为 navigator.credentials.get
中 configURL
的路径部分。数组中的网址字符串数量不得超过 1 个,但将来可能会根据您的反馈而有所变化。
创建 IdP 配置文件和端点
IdP 配置文件为浏览器提供了必需端点的列表。IdP 将托管此配置文件以及所需的端点和网址。所有 JSON 响应都必须使用 application/json
内容类型提供。
配置文件的网址由向 RP 上执行的 navigator.credentials.get
调用提供的值决定。
const credential = await navigator.credentials.get({
identity: {
context: 'signup',
providers: [{
configURL: 'https://accounts.idp.example/config.json',
clientId: '********',
nonce: '******'
}]
}
});
const { token } = credential;
将 IdP 配置文件位置的完整网址指定为 configURL
。在 RP 上调用 navigator.credentials.get()
时,浏览器会使用不含 Origin
标头或 Referer
标头的 GET
请求提取配置文件。请求不含 Cookie,也不遵循重定向。
这样做可有效防止 IdP 了解是谁发出了请求以及哪个 RP 正在尝试建立连接。例如:
GET /config.json HTTP/1.1
Host: accounts.idp.example
Accept: application/json
Sec-Fetch-Dest: webidentity
浏览器希望从 IdP 收到 JSON 响应,其中包含以下属性:
属性 | 说明 |
---|---|
accounts_endpoint (必需) |
accounts 端点的网址。 |
client_metadata_endpoint (可选) |
客户端元数据端点的网址。 |
id_assertion_endpoint (必需) |
ID 断言端点的网址。 |
disconnect (可选) |
断开连接端点的网址。 |
login_url (必需) |
用户登录 IdP 的登录页网址。 |
branding (可选) |
包含各种品牌选项的对象。 |
branding.background_color (可选) |
用于设置“继续以...身份操作”按钮背景颜色的品牌化选项。使用相关的 CSS 语法,即 hex-color 、hsl() 、rgb() 或 named-color 。 |
branding.color (可选) |
用于设置“继续以...身份操作”按钮文本颜色的品牌选项。使用相关的 CSS 语法,即 hex-color 、hsl() 、rgb() 或 named-color 。 |
branding.icons (可选) |
用于设置登录对话框中显示的图标对象的品牌化选项。图标对象是一个包含两个参数的数组:
|
RP 可以通过 navigator.credentials.get()
的 identity.context
值修改 FedCM 对话框界面中的字符串,以适应预定义的身份验证上下文。可选属性可以是 "signin"
(默认)、"signup"
、"use"
或 "continue"
之一。
以下是身份提供程序的响应正文示例:
{
"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 上登录的账号列表。如果 IdP 支持多个账号,此端点将返回所有已登录的账号。
浏览器发送包含 Cookie 的 GET
请求,其中包含 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
收到请求后,服务器应执行以下操作:
- 验证请求是否包含
Sec-Fetch-Dest: webidentity
HTTP 标头。 - 将会话 Cookie 与已登录账号的 ID 进行匹配。
- 响应并提供账号列表。
浏览器预期 JSON 响应包含一个 accounts
属性,其中包含具有以下属性的账号信息数组:
属性 | 说明 |
---|---|
id (必需) |
用户的唯一 ID。 |
name (必需) |
用户的名字和姓氏。 |
email (必需) |
用户的电子邮件地址。 |
given_name (可选) |
用户的名字。 |
picture (可选) |
用户头像图片的网址。 |
approved_clients (可选) |
用户已注册的 RP 客户端 ID 的数组。 |
login_hints (可选) |
一个数组,包含 IdP 支持指定账号的所有可能的过滤条件类型。RP 可以通过 loginHint 属性调用 navigator.credentials.get() ,以选择性地显示指定的账号。 |
domain_hints (可选) |
账号关联的所有网域的数组。RP 可以使用 domainHint 属性调用 navigator.credentials.get() 来过滤账号。 |
响应正文示例:
{
"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 注册,系统会在登录对话框中显示这些链接。
浏览器使用不带 Cookie 的 client_id
navigator.credentials.get
发送 GET
请求。例如:
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
收到请求后,服务器应执行以下操作:
- 确定
client_id
的 RP。 - 使用客户端元数据进行响应。
客户端元数据端点的属性包括:
属性 | 说明 |
---|---|
privacy_policy_url (可选) |
RP 隐私权政策网址。 |
terms_of_service_url (可选) |
RP 服务条款网址。 |
浏览器会要求从该端点返回 JSON 响应:
{
"privacy_policy_url": "https://rp.example/privacy_policy.html",
"terms_of_service_url": "https://rp.example/terms_of_service.html",
}
返回的客户端元数据会被浏览器使用,并且不可用于 RP。
ID 断言端点
IdP 的 ID 断言端点会为其已登录的用户返回断言。当用户使用 navigator.credentials.get()
调用登录 RP 网站时,浏览器会向此端点发送包含 SameSite=None
的 Cookie 和内容类型为 application/x-www-form-urlencoded
的 POST
请求,其中包含以下信息:
属性 | 说明 |
---|---|
client_id (必需) |
RP 的客户端标识符。 |
account_id (必需) |
登录用户的唯一 ID。 |
nonce (可选) |
请求 Nonce,由 RP 提供。 |
disclosure_text_shown |
返回 "true" 或 "false" 字符串(而不是布尔值)。如果未显示披露文本,则结果为 "false" 。如果 RP 的客户 ID 包含在 accounts 端点响应的 approved_clients 属性列表中,或者浏览器在过去观察到注册时刻时未检测到 approved_clients ,就会出现这种情况。 |
is_auto_selected |
如果对 RP 执行了自动重新身份验证,则 is_auto_selected 表示 "true" 。否则为 "false" 。这有助于支持更多与安全相关的功能。例如,某些用户可能更喜欢更高的安全级别,这要求在身份验证中采用显式用户中介。如果 IdP 收到的令牌请求没有使用此类中介,则可能会以其他方式处理该请求。例如,返回一个错误代码,以便 RP 可以使用 mediation: required 再次调用 FedCM API。 |
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
收到请求后,服务器应执行以下操作:
- 使用 CORS(跨源资源共享)响应请求。
- 验证请求是否包含
Sec-Fetch-Dest: webidentity
HTTP 标头。 - 将
Origin
标头与由client_id
确定的 RP 来源进行匹配。如果不匹配,请拒绝。 - 将
account_id
与已登录账号的 ID 进行匹配。如果不匹配,则拒绝。 - 使用令牌进行响应。如果请求被拒绝,请返回错误响应。
令牌的签发方式取决于 IdP,但通常,令牌使用账号 ID、客户端 ID、签发者来源 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
:用于标识包含错误相关信息的人类可读网页,以向用户提供有关错误的更多信息。此字段对用户很有用,因为浏览器无法在原生界面中提供丰富的错误消息。例如,后续步骤的链接、客户服务联系信息等。如果用户想要详细了解错误详情和修正方法,可以通过浏览器界面访问所提供的页面了解详情。该网址必须与 IdPconfigURL
位于同一网站。
// id_assertion_endpoint response
{
"error" : {
"code": "access_denied",
"url" : "https://idp.example/error?type=access_denied"
}
}
断开端点
通过调用 IdentityCredential.disconnect()
,浏览器会向此断开连接端点发送包含 SameSite=None
和内容类型为 application/x-www-form-urlencoded
的跨源 POST
请求,其中包含以下信息:
属性 | 说明 |
---|---|
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
收到请求后,服务器应执行以下操作:
- 使用 CORS(跨源资源共享)响应请求。
- 验证请求是否包含
Sec-Fetch-Dest: webidentity
HTTP 标头。 - 将
Origin
标头与由client_id
确定的 RP 源进行匹配。如果不匹配,请拒绝。 - 将
account_hint
与已登录账号的 ID 进行匹配。 - 解除用户账号与 RP 的关联。
- 以 JSON 格式向浏览器响应已识别的用户账号信息。
响应 JSON 载荷示例如下:
{
"account_id": "account456"
}
相反,如果 IdP 希望浏览器解除与 RP 关联的所有账号,请传递与任何账号 ID 都不匹配的字符串,例如 "*"
。
登录网址
使用 Login Status API 时,IdP 必须向浏览器告知用户的登录状态。不过,状态可能会不同步,例如在会话过期时。在这种情况下,浏览器可以通过使用 idp 配置文件的 login_url
指定的登录页面网址,动态让用户登录 IdP。
FedCM 对话框会显示一条提示登录的消息,如下图所示。
当用户点击 Continue 按钮时,浏览器会为 IdP 的登录页面打开一个弹出式窗口。
该对话框是一个包含第一方 Cookie 的常规浏览器窗口。对话框中发生的任何情况都取决于 IdP,并且没有窗口句柄可用于向 RP 页面发出跨源通信请求。用户登录后,IdP 应执行以下操作:
- 发送
Set-Login: logged-in
标头或调用navigator.login.setStatus("logged-in")
API 以告知浏览器用户已登录。 - 调用
IdentityProvider.close()
以关闭对话框。
告知浏览器用户在身份提供程序中的登录状态
Login Status API 是一种机制,在该机制中,网站(尤其是 IdP)会将用户在 IdP 上的登录状态告知浏览器。借助此 API,浏览器可以减少对 IDP 的不必要请求,并缓解潜在的时间攻击。
当用户在 IdP 上登录或退出所有 IdP 账号时,IdP 可以通过发送 HTTP 标头或调用 JavaScript API 向浏览器发送用户的登录状态信号。对于每个 IdP(通过其配置网址进行标识),浏览器都会保留一个三态变量来表示登录状态,可能的值为 logged-in
、logged-out
和 unknown
。默认状态为 unknown
。
如需指示用户已登录,请在顶级导航中发送 Set-Login: logged-in
HTTP 标头,或在 IdP 源中发送同一网站子资源请求:
Set-Login: logged-in
或者,您也可以在顶级导航栏中的 IdP 来源中调用 JavaScript API navigator.login.setStatus("logged-in")
:
navigator.login.setStatus("logged-in")
这些调用会将用户的登录状态记录为 logged-in
。当用户的登录状态设置为 logged-in
时,调用 FedCM 的 RP 会向 IdP 的账号端点发出请求,并在 FedCM 对话框中向用户显示可用账号。
如需指示用户已退出所有账号,请在顶级导航中发送 Set-Login:
logged-out
HTTP 标头,或在 IdP 源中发送同一网站子资源请求:
Set-Login: logged-out
或者,在顶级导航中,从 IdP 源调用 JavaScript API navigator.login.setStatus("logged-out")
:
navigator.login.setStatus("logged-out")
这些调用会将用户的登录状态记录为 logged-out
。当用户的登录状态为 logged-out
时,调用 FedCM 会静默失败,而不会向 IdP 的账号端点发出请求。
在 IdP 使用 Login Status API 发送信号之前,系统会设置 unknown
状态。我们引入了 Unknown
来实现更好的转换效果,因为在此 API 交付时,用户可能已经登录 IdP。在首次调用 FedCM 时,IdP 可能没有机会向浏览器发出此信号。在这种情况下,Chrome 会向 IdP 的账号端点发出请求,并根据账号端点的响应更新状态:
- 如果端点返回活跃账号的列表,请将状态更新为
logged-in
并打开 FedCM 对话框以显示这些账号。 - 如果端点未返回任何账号,请将状态更新为
logged-out
并使 FedCM 调用失败。
让用户通过动态登录流程登录
即使 IdP 会持续向浏览器告知用户的登录状态,但状态也可能会不同步,例如在会话过期时。当登录状态为 logged-in
时,浏览器会尝试向账号端点发送一个经过凭据验证的请求,但服务器未返回任何账号,因为该会话不再可用。在这种情况下,浏览器可以动态地允许用户通过弹出式窗口登录 IdP。
使用身份提供方登录信赖方
IdP 的配置和端点可用后,RP 可以调用 navigator.credentials.get()
来请求允许用户通过 IdP 登录 RP。
在调用该 API 之前,您需要确认 [FedCM 在用户的浏览器上可用]。如需检查 FedCM 是否可用,请将此代码封装在 FedCM 实现中:
if ('IdentityCredential' in window) {
// If the feature is available, take action
}
如需请求允许用户从 RP 登录 IdP,请执行以下操作,例如:
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 (必需) |
IdP 签发的 RP 客户端标识符。 |
nonce (可选) |
一个随机字符串,确保针对此特定请求发出响应。防范重放攻击。 |
loginHint (可选) |
通过指定 accounts 端点提供的 login_hints 值之一,FedCM 对话框会选择性地显示指定的账号。 |
domainHint (可选) |
通过指定账号端点提供的 domain_hints 值之一,FedCM 对话框会选择性地显示指定的账号。 |
浏览器会根据 accounts list 端点响应中是否存在 approved_clients
来不同地处理注册和登录用例。如果用户已注册 RP,浏览器将不会显示披露文本“To continue with ....”(如要继续...)。
注册状态取决于是否满足以下条件:
- 如果
approved_clients
包含 RP 的clientId
。 - 如果浏览器记得用户已注册 RP。
当 RP 调用 navigator.credentials.get()
时,会发生以下 activity:
- 浏览器发送请求并提取多个文档:
- 浏览器会显示用户可以用于登录的账号列表,以及服务条款和隐私权政策(如果有)。
- 用户选择用于登录的账号后,系统会将对 ID 断言端点的请求发送到 IdP,以检索令牌。
- RP 可以验证令牌以对用户进行身份验证。
RP 应支持不支持 FedCM 的浏览器,因此用户应能够使用现有的非 FedCM 登录流程。在第三方 Cookie 完全淘汰之前,这应该不会造成问题。
令牌由 RP 服务器验证后,RP 可以注册用户,也可以让用户登录并开始新的会话。
Login Hint API
用户登录后,有时信赖方 (RP) 会要求用户重新进行身份验证。但用户可能不确定自己使用的是哪个账号。如果 RP 可以指定要使用哪个账号登录,用户便可以更轻松地选择账号。
RP 可以通过将 loginHint
属性与从账号列表端点提取的 login_hints
值之一一起调用 navigator.credentials.get()
,以选择性地显示特定账号,如以下代码示例所示:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "123",
nonce: nonce,
loginHint : "demo1@example.com"
}]
}
});
如果没有账号与 loginHint
匹配,FedCM 对话框会显示登录提示,以便用户登录与 RP 请求的提示相符的 IdP 账号。当用户点按提示时,系统会打开一个弹出式窗口,其中包含配置文件中指定的登录网址。然后,该链接会附加登录提示和网域提示查询参数。
Domain Hint API
在某些情况下,RP 已知晓只有与特定网域关联的账号才能登录该网站。在企业场景中,这种情况尤其常见,因为在这种场景中,被访问的网站仅限于公司网域。为了提供更好的用户体验,FedCM API 允许 RP 仅显示可用于登录 RP 的账号。这样可以防止出现以下情况:用户尝试使用公司网域之外的账号登录 RP,但由于未使用正确类型的账号,系统稍后会显示错误消息(或在登录失败时保持沉默)。
RP 可以通过将 domainHint
属性与从账号列表端点提取的 domain_hints
值之一一起调用 navigator.credentials.get()
,从而选择性地仅显示匹配的账号,如以下代码示例所示:
return await navigator.credentials.get({
identity: {
providers: [{
configURL: "https://idp.example/manifest.json",
clientId: "abc",
nonce: nonce,
domainHint : "corp.example"
}]
}
});
如果没有账号与 domainHint
匹配,FedCM 对话框会显示登录提示,以便用户登录与 RP 请求的提示相符的 IdP 账号。当用户点按提示时,系统会打开一个弹出式窗口,其中包含配置文件中指定的登录网址。然后,在链接后附加登录提示和网域提示查询参数。
显示错误消息
有时,身份提供方可能出于合法原因而无法签发令牌,例如客户端未经授权、服务器暂时不可用。如果 IdP 返回“错误”响应,RP 可以捕获该响应,Chrome 也会通过显示包含 IdP 提供的错误信息的浏览器界面来通知用户。
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 自动重新身份验证(简称“auto-reauthn”)可让用户在使用 FedCM 进行初始身份验证后再次访问时自动重新进行身份验证。这里的“初始身份验证”是指用户在同一浏览器实例中首次点按 FedCM 登录对话框中的“Continue as...” 按钮,创建账号或登录 RP 的网站。
虽然在用户创建联合账号以防止跟踪(这是 FedCM 的主要目标之一)之前,明确的用户体验很有意义,但在用户完成一次体验后,再次执行此体验会不必要地繁琐:在用户授予允许 RP 与 IdP 之间通信的权限后,再强制用户针对他们之前已确认的内容再次明确确认,对隐私或安全没有任何好处。
使用自动重新授权时,浏览器会根据您在调用 navigator.credentials.get()
时为 mediation
指定的选项来更改其行为。
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
是 Credential Management API 中的属性,其行为与 PasswordCredential 和 FederatedCredential 相同,并且 PublicKeyCredential 也对其提供部分支持。该属性接受以下四个值:
'optional'
(默认):如果可能自动重新验证,则需要中介。我们建议您在登录页面上选择此选项。'required'
:始终需要中介才能继续,例如点击界面上的“继续”按钮。如果您希望用户每次需要进行身份验证时都明确授予权限,请选择此选项。'silent'
:如果可能,自动重新授权;如果不可能,则静默失败,无需中介。我们建议在专用登录页面以外的页面(例如,物流网站上的商品页面或新闻网站上的文章页面)上选择此选项。'conditional'
:用于 WebAuthn,目前不适用于 FedCM。
此调用会在以下情况下自动重新验证:
- FedCM 可供使用。例如,用户尚未在整个平台中停用 FedCM,或未在设置中为 RP 停用 FedCM。
- 在此浏览器中,用户仅使用了一个具有 FedCM API 的账号登录网站。
- 用户已使用该账号登录 IdP。
- 过去 10 分钟内未发生自动重新验证。
- RP 在上次登录后未调用
navigator.credentials.preventSilentAccess()
。
满足这些条件后,系统会在调用 FedCM navigator.credentials.get()
后立即开始自动对用户重新进行身份验证。
当 mediation: optional
时,由于只有浏览器知道的原因,自动重新授权可能不可用;RP 可以通过检查 isAutoSelected
属性来检查是否执行了自动重新授权。
这有助于评估 API 性能并相应地改善用户体验。
此外,在 API 不可用时,系统可能会提示用户通过显式用户中介(使用 mediation: required
的流程)登录。
使用 preventSilentAccess()
强制执行中介
在用户退出账号后立即自动重新验证用户身份,并不能提供非常良好的用户体验。因此,FedCM 在自动重新验证后会有 10 分钟的静默期,以防止此行为。这意味着,除非用户在 10 分钟内重新登录,否则系统每 10 分钟最多会自动重新授权一次。当用户明确退出 RP(例如,点击“退出”按钮)时,RP 应调用 navigator.credentials.preventSilentAccess()
以明确请求浏览器停用自动重新授权。
function signout() {
navigator.credentials.preventSilentAccess();
location.href = '/signout';
}
用户可以在设置中选择停用自动重新授权
用户可以在“设置”菜单中选择停用自动重新授权:
- 在桌面版 Chrome 中,依次选择
chrome://password-manager/settings
> 自动登录。 - 在 Android Chrome 中,依次打开设置 > 密码管理工具 > 点按右上角的齿轮图标 > 自动登录。
通过停用此切换开关,用户可以完全停用自动重新授权行为。如果用户在 Chrome 实例中登录了 Google 账号并启用了同步功能,系统会存储此设置并在设备间同步。
断开 IdP 与 RP 之间的连接
如果用户之前通过 FedCM 使用 IdP 登录了 RP,浏览器会在本地将该关系记忆为已关联账号的列表。RP 可以通过调用 IdentityCredential.disconnect()
函数来发起断开连接。此函数可从顶级 RP 帧调用。RP 需要传递 configURL
、在 IdP 下使用的 clientId
以及 accountHint
,以便 IdP 断开连接。账号提示可以是任意字符串,只要断开连接端点可以识别账号即可,例如电子邮件地址或用户 ID,该 ID 不一定与账号列表端点提供的账号 ID 相匹配:
// 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
。此 promise 可能会因以下原因抛出异常:
- 用户尚未通过 FedCM 使用 IdP 登录 RP。
- 从不含 FedCM 权限政策的 iframe 中调用 API。
- config网址 无效或缺少断开连接端点。
- 内容安全政策 (CSP) 检查失败。
- 有一个待处理的解除关联请求。
- 用户已在浏览器设置中停用 FedCM。
当身份提供方的断开连接端点返回响应时,浏览器上的 RP 和 IdP 会断开连接,并且 Promise 会解析。断开连接的账号的 ID 在断开连接端点的响应中指定。
从跨源 iframe 内调用 FedCM
您可以使用 identity-credentials-get
权限政策从跨源 iframe 中调用 FedCM(如果父级框架允许)。为此,请将 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")
您可以参阅使用权限政策控制浏览器功能,详细了解“权限”政策的运作方式。