允许通过相关源请求在您的各个网站上重复使用通行密钥

通行密钥与特定网站绑定,只能用于登录创建时对应的网站。

这在依赖方 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"
  ]
}

下次这些网站中的任何一个调用通行密钥创建 (navigator.credentials.create) 或身份验证 (navigator.credentials.get)(使用 example.com 作为 RP ID)时,浏览器会注意到 RP ID 与请求来源不匹配。如果浏览器支持相关源请求,则会先在 https://{RP ID}/.well-known/webauthn 查找 webauthn 文件。如果该文件存在,浏览器会检查发出请求的来源是否在 allowlist 中。如果是,则继续执行通行密钥创建或身份验证步骤。

如果浏览器不支持关联源请求,则会抛出 SecurityError。

浏览器支持

Chrome 和 Safari 支持关联源请求。截至 2026 年 1 月,Firefox 仍在考虑是否支持该功能。您可以在 Mozilla 标准立场问题中跟踪其状态。

以下演示使用了两个网站: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。
Chrome 会在这两个网站上自动填充。
借助相关来源请求,用户可以在 ror-1 和 ror-2 中使用相同的通行密钥凭证。Chrome 还会自动填充凭据。

查看代码:

第 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:

  • 创建凭证时:
    • 在传递给 navigator.credentials.create 前端调用的凭据创建 options 中,将 site-1.com 设置为 RP ID,通常在服务器端生成。
    • 在将凭据保存到数据库之前,请先运行凭据验证,并将 site-1.com 设置为预期的 RP ID。
  • 身份验证后:
    • 在传递给 navigator.credentials.get 前端调用的身份验证 options 中,将 site-1.com 设置为 RP ID,该 ID 通常在服务器端生成。
    • 在对用户进行身份验证之前,请先运行凭据验证,并将 site-1.com 设置为要在服务器上验证的预期 RP ID。

问题排查

Chrome 中弹出的出错提示。
创建凭据时 Chrome 中显示的错误消息。如果无法在 `https://{RP ID}/.well-known/webauthn` 找到 `.well-known/webauthn` 文件,系统会抛出此错误。
Chrome 中弹出的出错提示。
创建凭证时 Chrome 中显示的错误消息。如果可以找到您的 `.well-known/webauthn` 文件,但该文件未列出您尝试从中创建凭证的来源,则会抛出此错误。

其他注意事项

在网站和移动应用之间共享通行密钥

借助关联源请求,用户可以在多个网站上重复使用通行密钥。如需允许用户在网站和移动应用中重复使用通行密钥,请使用以下方法:

跨网站共享密码

关联源请求允许用户跨网站重复使用通行密钥。 不同密码管理工具在跨网站共享密码方面的解决方案各不相同。 对于 Google 密码管理工具,请使用 Digital Asset Links 。 Safari 采用不同的系统。

Credential Manager 和用户代理的角色

这超出了您作为网站开发者的职责范围,但请注意,从长远来看,RP ID 不应是用户代理或用户使用的 Credential Manager 中用户可见的概念。相反,用户代理和凭证管理器应向用户显示其凭证的使用位置。这项变更需要一段时间才能实施。临时解决方案是同时显示当前网站和原始注册网站。