“相关来源请求”解决的问题
通行密钥与特定网站相关联,只能用于登录创建时对应的网站。
这在依赖方 ID (RP ID) 中指定,对于为 example.com 网域创建的通行密钥,此 ID 可以是 www.example.com
或 example.com
。
虽然 RP ID 可防止通行密钥被用作在所有位置进行身份验证的单一凭据,但会导致以下问题:
- 包含多个网域的网站:用户无法使用相同的通行密钥在同一公司管理的不同国家/地区专用网域(例如
example.com
和example.co.uk
)中登录。 - 品牌网域:用户无法在单个品牌使用的不同网域(例如
acme.com
和acmerewards.com
)中使用相同的凭据。 - 移动应用:移动应用通常没有自己的网域,因此很难管理凭据。
有一些基于身份联合的权宜解决方法,还有一些基于 iframe 的权宜解决方法,但在某些情况下,这些方法并不方便。“相关的来源请求”提供了解决方案。
解决方案
借助相关来源请求,网站可以指定允许使用其 RP ID 的来源。
这样,用户就可以在您运营的多个网站上重复使用同一通行密钥。
如需使用相关来源请求,您需要在特定网址 https://{RP ID}/.well-known/webauthn
上提供特殊的 JSON 文件。如果 example.com
希望允许其他来源将其用作 RP ID,则应在 https://example.com/.well-known/webauthn:
上提供以下文件
{
"origins": [
"https://example.co.uk",
"https://example.de",
"https://example-rewards.com"
]
}
下次这些网站中的任何一个网站调用使用 example.com
作为 RP ID 的通行密钥创建 (navigator.credentials.create
) 或身份验证 (navigator.credentials.get
) 时,浏览器会注意到 RP ID 与请求来源不匹配。如果浏览器支持相关来源请求,则会先在 https://{RP ID}/.well-known/webauthn
中查找 webauthn
文件。如果该文件存在,浏览器会检查发出请求的来源是否已列入该文件的许可名单。如果是,则会继续执行通行密钥创建或身份验证步骤。
如果浏览器不支持相关源请求,则会抛出 SecurityError
。
浏览器支持
- Chrome:从 Chrome 128 开始受支持。
- Safari:从 macOS 15 Beta 版 3 开始受支持,移动设备上的 iOS 18 Beta 版 3 也受支持。
- Firefox:等待位置。
如何设置相关来源请求
以下演示使用了两个网站 https://ror-1.glitch.me
和 https://ror-2.glitch.me
的示例。
为了让用户能够在这两个网站上使用相同的通行密钥登录,它使用相关来源请求允许 ror-2.glitch.me
使用 ror-1.glitch.me
作为其 RP ID。
演示
https://ror-2.glitch.me 实现了相关来源请求,以使用 ror-1.glitch.me 作为 RP ID,因此 ror-1
和 ror-2
在创建通行密钥或使用通行密钥进行身份验证时都会使用 ror-1.glitch.me
作为 RP ID。
我们还在这些网站上实现了共享通行密钥数据库。
观察以下用户体验:
- 您可以在
ror-2
上成功创建通行密钥并使用该通行密钥进行身份验证,即使其 RP ID 为ror-1
(而非ror-2
)也是如此。 - 在
ror-1
或ror-2
上创建通行密钥后,您可以在ror-1
和ror-2
上使用该通行密钥进行身份验证。由于ror-2
将ror-1
指定为 RP ID,因此从这些网站中的任何一个网站发出通行密钥创建请求或身份验证请求,都与在 ror-1 上发出请求一样。RP ID 是将请求与来源相关联的唯一依据。 - 在
ror-1
或ror-2
上创建通行密钥后,Chrome 可以在ror-1
和ror-2
上自动填充该通行密钥。 - 在上述任一网站上创建的凭据的 RP ID 均为
ror-1
。
查看代码:
第 1 步:实现共享账号数据库
如果您希望用户能够在 site-1
和 site-2
上使用相同的通行密钥进行登录,请实现一个在两个网站上共享的账号数据库。
第 2 步:在 site-1 中设置 .well-known/webauthn JSON 文件
首先,配置 site-1.com
,以允许 site-2.com
将其用作 RP ID。为此,请创建 webauthn JSON 文件:
{
"origins": [
"https://site-2.com"
]
}
JSON 对象必须包含一个名为 origins 的键,其值是一个包含一个或多个网页来源字符串的数组。
重要限制:最多 5 个标签
系统会处理此列表中的每个元素,以提取 eTLD + 1 标签。例如,example.co.uk
和 example.de
的 eTLD + 1 标签均为 example
。但 example-rewards.com
的 eTLD+1 标签为 example-rewards
。在 Chrome 中,标签数量上限为 5 个。
第 3 步:在 site-1 中提供 .well-known/webauthn JSON
然后,在 site-1.com/.well-known/webauthn
下提供 JSON 文件。
例如,在 Express 中:
app.get("/.well-known/webauthn", (req, res) => {
const origins = {
origins: ["https://site-2.com"],
};
return res.json(origins);
});
在这里,我们使用的是 Express res.json
,它已设置正确的 content-type
('application/json'
);
第 4 步:在 site-2 中指定所需的 RP ID
在 site-2
代码库中,在需要的所有位置将 site-1.com
设置为 RP ID:
- 在创建凭据时:
- 在凭据创建
options
中将site-1.com
设置为 RP ID,这些 ID 会传递给navigator.credentials.create
前端调用,通常由服务器端生成。 - 将
site-1.com
设置为预期的 RP ID,因为您会在将凭据保存到数据库之前运行凭据验证。
- 在凭据创建
- 身份验证后:
- 在传递给
navigator.credentials.get
前端调用的身份验证options
中将site-1.com
设置为 RP ID,通常在服务器端生成。 - 将
site-1.com
设置为要在服务器上验证的预期 RP ID,因为您会在对用户进行身份验证之前运行凭据验证。
- 在传递给
问题排查
其他注意事项
在网站和移动应用之间共享通行密钥
借助相关源请求,您的用户可以在多个网站中重复使用通行密钥。如需允许用户在网站和移动应用中重复使用通行密钥,请使用以下方法:
- 在 Chrome 中:Digital Asset Links。如需了解详情,请参阅添加对 Digital Asset Links 的支持。
- 在 Safari 中:关联的网域。
在不同网站中共享密码
借助相关来源请求,您的用户可以在不同网站上重复使用通行密钥。不同密码管理工具提供的跨网站密码共享解决方案各不相同。对于 Google 密码管理工具,请使用 Digital Asset Links 。Safari 使用其他系统。
凭据管理器和用户代理的角色
这超出了您作为网站开发者的职责范围,但请注意,从长远来看,RP ID 不应是用户代理或用户使用的凭据管理器中向用户显示的概念。相反,用户代理和凭据管理器应向用户显示其凭据的使用位置。这项变更需要一些时间才能实施。临时解决方案是同时显示当前网站和原始注册网站。