凭证管理级别 1

W3C 工作草案

关于此文档的更多细节
此版本
https://w3org.cn/TR/2026/WD-credential-management-1-20260410/
最新发布版本
https://w3org.cn/TR/credential-management-1/
编辑草案
https://w3c.github.io/webappsec-credential-management/
历史版本
历史
https://w3org.cn/standards/history/credential-management-1/
反馈
public-webappsec@w3.org,主题行需包含“[credential-management] … 消息主题 …”(归档
GitHub
编辑
(Google Inc.)
(Apple Inc.)
前任编辑
(Google Inc.)
(Google Inc.)
参与贡献
提交问题 (开放的问题)

摘要

本规范描述了一个指令式 API,允许网站向用户代理请求用户的凭据,并帮助用户代理正确存储用户凭据以供未来使用。

关于本文档

本节描述了本文件在发布时的状态。当前的 W3C 出版物列表和本技术报告的最新修订版可在 W3C 技术报告索引中找到。

本文档由 Web Application Security Working Group 作为工作草案发布,采用 Recommendation track。本文档旨在成为 W3C 推荐标准。

建议使用(归档的)公共邮件列表 public-webappsec@w3.org(参见说明)讨论本规范。发送电子邮件时,请在主题中加入“credential-management”,建议格式为:“[credential-management] …评论摘要…

以工作草案形式发布并不意味着得到 W3C 及其成员的认可。这是草稿文件,可能随时被更新、替换或废止。引用此文档时应说明它仍在进行中。

本文由 Web 应用安全工作组 编写。

本文档由在 W3C 专利政策 下运作的工作组编写。W3C 维护一份 公开的专利披露列表,其中列出了与该工作组交付物相关的任何专利披露;该页面还包括披露专利的说明。任何实际了解某项专利且认为该专利包含 Essential Claim(s) 的个人,必须按照 W3C 专利政策第 6 节的规定进行披露。

本文件受 2025 年 8 月 18 日 W3C 流程文件的管辖。

1. 引言

本节不具有规范性。

登录网站比应当更加困难。用户代理在以多种方式改善体验方面处于独特地位,大多数现代用户代理已通过在浏览器中提供一定程度的凭据管理功能来认识到这一点。例如,用户可以保存网站的用户名和密码;这些凭据随后会被自动填充到登录表单中,尽管成功率各不相同。

autocomplete 属性提供了一种声明式机制,网站可以通过该机制与用户代理协作,提高后者检测和填充登录表单的能力,方法是将特定字段标记为“用户名”或“密码”。用户代理实现了多种检测启发法,以与未在标记中提供此详细信息的网站协作。

虽然这种启发式和声明式检测的结合工作得相对较好,但现状留下了一些检测存在问题的巨大差距。具有不常见登录机制(例如通过 XMLHttpRequest [XMLHTTPREQUEST] 提交凭据)的网站很难可靠地检测到,用户希望使用联合身份提供商进行身份验证的情况也越来越普遍。允许网站更直接地与用户代理的凭据管理器交互,一方面可以使凭据管理器更加准确,另一方面可以协助用户进行联合登录。

这些用例在 § 1.1 用例 以及 凭据管理:用例与要求 中进行了更详细的探讨;本规范试图通过定义凭据管理器 API 来解决该文档概述的许多要求,网站可以使用该 API 为用户请求凭据,并请求用户代理在用户成功登录时持久化凭据。

注意:此处定义的 API 有意保持简洁:它本身并不打算提供身份验证,而是仅限于提供一个接口,连接到现有用户代理实现的现有凭据管理器。该功能在目前就很有价值,无需供应商或作者付出巨大的努力。当然,还有很多工作可以做。请参阅 § 9 未来工作,了解我们暂时搁置但可以在此 API 的未来迭代中探索的一些想法。

1.1. 用例

现代用户代理通常为用户提供在登录网站时保存密码的能力,同样也提供在用户返回网站时全自动或半自动地将这些密码填充到登录表单中的能力。从网站的角度来看,这种行为是完全不可见的:网站不知道密码已被存储,也不知道密码已被填充。这既有优点也有缺点。一方面,用户代理的密码管理器无论网站是否配合都能工作,这对用户来说是非常好的。另一方面,密码管理器的行为是一个脆弱且专有的启发式混合体,旨在检测和填充登录表单、密码修改表单等。

现状中的几个问题尤其值得注意。

2. 核心 API

从开发者的角度来看,凭据是一个对象,允许开发者为特定操作做出身份验证决策。本节定义了一个通用且可扩展的 Credential 接口,作为本文档和其他文档中定义的凭据的基类,以及挂载在 navigator.credentials.* 上的一组 API,使开发者能够获取它们。

各种凭据类型在 JavaScript 中分别表示为一个接口,该接口直接或间接地继承Credential 接口。本文档定义了两个此类接口:PasswordCredentialFederatedCredential。其他规范(例如 [WEBAUTHN])定义了其他凭据类型。

如果一个凭据被特定接受为该源上的身份验证,则它对该源是有效的。即使凭据在特定时间点有效,用户代理也不能假设同一个凭据在未来的任何时间点仍然有效,原因有两个:

  1. 如果账户持有人更改了密码,密码凭据可能会停止有效。

  2. 通过短信收到的令牌制作的凭据可能仅对单次使用有效。

一次性凭据是由凭据来源生成的,这可能是私钥、对联合账户的访问权限、在特定电话号码上接收短信的能力或其他事物。凭据来源不会暴露给 Javascript,也不会在本规范中明确表示。为了统一模型,我们将密码视为一种独立的凭据来源,仅仅通过复制它来创建密码凭据。

即使 UA 不能假设有效的凭据如果再次使用仍然有效,或者产生有效凭据的凭据来源将来能够产生第二个有效凭据,但第二种情况比第一种更有可能。通过记录(使用 store())哪些凭据在过去是有效的,UA 在将来更有可能用户提供有效的凭据来源。

2.1. 基础设施

凭据管理器是一个应用程序、硬件设备或服务,它存储、组织、管理并允许选择凭据。示例凭据管理器包括数字钱包、密码管理器和通行密钥 (passkey) 管理器。

用户代理必须在内部提供一个凭据存储,这是一个特定于供应商的不透明存储机制,用于记录哪些凭据有效的。它为凭据访问和持久化提供以下能力:

  1. 存储凭据以供日后检索。此操作接受一个凭据,并将其插入凭据存储中。

  2. 检索凭据列表。此操作接受任意过滤器,并返回与过滤器匹配的一组凭据

  3. 修改凭据。此操作接受一个凭据,并覆盖凭据存储中现有凭据的状态。

此外,凭据存储应为维护一个禁止静默访问标志(除非另有说明,否则设置为 true)。如果源的标志设置为 true,则该源需要用户中介

注意:用户中介的重要性在 § 5 用户中介 中有更详细的讨论。

注意:凭据存储是用户代理实现本文档中指定的 API 的内部实现细节,不会直接暴露给 Web。为了支持特定凭据类型,其他文档可能会指定更多能力。

本文档依赖于 Infra 标准来获取其算法和正文中使用的许多基础概念 [INFRA]

每个环境设置对象都有一个关联的激活的凭据类型,这是一个初始为空的集合

2.1.1. 基础设施算法

2.1.1.1. 与祖先同源

如果以下算法返回 true,则环境设置对象settings)被认为是与祖先同源的:

  1. 如果 settings相关全局对象没有关联文档,则返回 false

  2. documentsettings相关全局对象关联文档

  3. 如果 document 没有浏览上下文,则返回 false

  4. originsettings

  5. navigabledocument节点导航器

  6. navigable 具有非空的父级时:

    1. navigable 设置为 navigable父级

    2. 如果 navigable活动文档origin同源,则返回 false

  7. 返回 true

2.1.2. 凭据类型注册表

该注册表将凭据类型(即 [[type]] 值)映射到与给定凭据类型关联的各种值。例如:选项成员标识符(形式上是一个字典成员标识符),其规范在 CredentialCreationOptionsCredentialRequestOptions(即“选项字典”)中使用。

注意:此注册表由相关凭据接口对象算法使用。

凭据类型
(按字母顺序)
选项成员标识符 适当的接口对象 Get 权限策略 Create 权限策略 允许在同一 get() 请求中使用的类型 规范请求者联系方式
digital-credential数字DigitalCredential digital-credentials-getnullempty [DIGITAL-CREDENTIALS] WICG
federatedfederatedFederatedCredential nullnull密码本文档:§ 4 联合凭据W3C
恒等 (identity)恒等 (identity)IdentityCredential identity-credentials-get nullempty [FEDCM] W3C
otpotpOTPCredential otp-credentials nullempty [WEB-OTP] WICG
密码密码PasswordCredential nullnullfederated本文档:§ 3 密码凭据W3C
public-keypublicKey(公钥)PublicKeyCredential publickey-credentials-get publickey-credentials-create empty [WEBAUTHN] W3C
2.1.2.1. 注册条目要求与更新流程

此注册表的更新是对凭据类型注册条目的添加、更改或删除。任何人都可以通过向 webappsec-credential-management 仓库提交 pull request 来请求更新此注册表。Web 应用安全工作组将把它放入即将召开的会议议程中,并通知请求者。对请求的审议和处置由 W3C Web 应用安全工作组通过共识决定。主席随后将通知请求者结果并相应地更新注册表。

2.2. Credential 接口

[Exposed=Window, SecureContext]
interface Credential {
  readonly attribute USVString id;
  readonly attribute DOMString type;
  static Promise<boolean> isConditionalMediationAvailable();
};
id 类型为 USVString,只读

凭据的标识符。每种凭据类型的标识符要求各不相同。例如,它可能表示用户名/密码元组的用户名。

type 类型为 DOMString,只读

此属性的 getter 返回对象接口对象[[type]] 插槽的值,该值指定此对象表示的凭据类型

isConditionalMediationAvailable()

返回一个 Promise,当且仅当用户代理支持针对该凭据类型凭据请求中介conditional 方法时,该 Promise 解析 (resolve)true,否则解析为 false

CredentialisConditionalMediationAvailable() 默认实现

  1. 返回一个解析为 false 的 promise。

任何支持 conditional 中介的凭据类型的规范必须明确覆盖此函数,以解析 (resolve)true

注意:如果此函数不存在,则该凭据类型不支持 conditional 中介。

[[type]]

Credential 接口对象有一个名为 [[type]] 的内部插槽,它不出所料地包含一个表示凭据类型的字符串。除非另有说明,否则插槽的值为空字符串。请参阅 § 2.1.2 凭据类型注册表 以获取凭据类型列表。

注意:[[type]] 插槽的值对于所有实现特定接口的凭据都是相同的,这意味着开发者可以依赖 obj.type 返回一个明确表示他们正在处理的特定类型 Credential 的字符串。

[[discovery]]

Credential 接口对象有一个名为 [[discovery]] 的内部插槽,表示用户代理可以收集给定类型凭据的机制。其值为 "credential store" 或 "remote"。前一个值表示所有可用的凭据信息都存储在用户代理的凭据存储中,而后者表示用户代理可以通过与某些外部设备或服务交互,发现那些未明确表示在凭据存储中的凭据。

与 Tobie/Dominic 讨论接口对象部分,这里和 § 2.5.1 请求 Credential 等处。我不确定我是否理解对了术语。接口原型对象,也许?

一些 Credential 对象是源绑定的:它们包含一个名为 [[origin]] 的内部插槽,用于存储 Credential 可能有效的

2.2.1. Credential 内部方法

Credential 接口对象具有多个促进 Credential 对象检索和存储的内部方法,并带有本节定义的默认“无操作”实现。

除非另有说明,否则为继承自 Credential 的接口创建的每个接口对象必须提供至少一个这些内部方法的实现,覆盖 Credential 的默认实现,具体取决于凭据类型。例如:§ 3.2 PasswordCredential 接口§ 4.1 FederatedCredential 接口[WEBAUTHN]

2.2.1.1. [[CollectFromCredentialStore]] 内部方法
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 被调用时,传入一个、一个 CredentialRequestOptions,以及一个布尔值,该布尔值当且仅当调用者的环境设置对象与祖先同源时为真。该算法返回用户代理凭据存储中匹配所提供选项的一组 Credential 对象。如果没有匹配的 Credential 对象可用,则返回的集合为空。

Credential[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 默认实现

  1. 返回一个空集。

2.2.1.2. [[DiscoverFromExternalSource]] 内部方法
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 并行调用,传入一个、一个 CredentialRequestOptions 对象,以及一个布尔值,该布尔值当且仅当调用者的环境设置对象与祖先同源时为真。它在给定所提供选项的情况下,如果可以返回一个 Credential,则返回该凭据;如果没有可用凭据,则返回 null;如果发现失败(例如,错误的选项可能会产生 TypeError),则抛出错误。如果此类 Credential 仅对单次使用或有限时间有效,则此方法负责使用凭据来源生成新的凭据

Credential[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 默认实现

  1. 返回 null

2.2.1.3. [[Store]] 内部方法
[[Store]](credential, sameOriginWithAncestors) 并行调用,传入一个 Credential,以及一个布尔值,该布尔值当且仅当调用者的环境设置对象与祖先同源时为真。算法在 Credential 持久化到凭据存储后返回。

Credential[[Store]](credential, sameOriginWithAncestors) 默认实现

  1. 抛出 NotSupportedError

2.2.1.4. [[Create]] 内部方法
[[Create]](origin, options, sameOriginWithAncestors) 并行调用,传入一个、一个 CredentialCreationOptions,以及一个布尔值,该布尔值当且仅当调用者的环境设置对象与祖先同源时为真。算法要么

创建 Credential 时,它将返回一个接收全局对象并返回继承自 Credential接口对象的算法。此算法必须从任务中调用。

注意:此算法的步骤基于每个凭据类型进行定义。

Credential[[Create]](origin, options, sameOriginWithAncestors) 默认实现

  1. 返回 null

2.2.2. CredentialUserData 混合项

一些 Credential 对象包含的数据旨在通过提供友好的名称和图标,在凭据选择器中为用户提供人类可读的消歧机制:

[SecureContext]
interface mixin CredentialUserData {
  readonly attribute USVString name;
  readonly attribute USVString iconURL;
};
name 类型为 USVString,只读

与凭据关联的名称,旨在作为在凭据选择器中显示的人类可理解的公共名称。

iconURL 类型为 USVString,只读

指向凭据图像的 URL,旨在在凭据选择器中显示。此 URL 必须是潜在可信 URL

2.3. navigator.credentials

开发者通过暴露在 CredentialsContainer 接口上的方法检索 Credential 并与用户代理的凭据存储交互,该接口挂载在 Navigator 对象上,作为 navigator.credentials

partial interface Navigator {
  [SecureContext, SameObject] readonly attribute CredentialsContainer credentials;
};

credentials 属性必须返回与活动文档浏览上下文关联的 CredentialsContainer

注意:§ 6.3 不安全站点 中所述,凭据管理 API 仅在安全上下文中暴露。

[Exposed=Window, SecureContext]
interface CredentialsContainer {
  Promise<Credential?> get(optional CredentialRequestOptions options = {});
  Promise<undefined> store(Credential credential);
  Promise<Credential?> create(optional CredentialCreationOptions options = {});
  Promise<undefined> preventSilentAccess();
};

dictionary CredentialData {
  required USVString id;
};
get(options)

当调用 get() 时,用户代理必须返回对 options 执行请求 Credential 的结果。

CredentialsContainer.get(options) 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
options CredentialRequestOptions 控制请求范围的属性集。
store(credential)

当调用 store() 时,用户代理必须返回对 credential 执行存储 Credential 的结果。

CredentialsContainer.store(credential) 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
凭据 (credential) 凭据 (Credential) 要存储的凭据。
create(options)

当调用 create() 时,用户代理必须返回对 options 执行创建 Credential 的结果。

CredentialsContainer.create(options) 方法的参数。
参数类型可为空 (Nullable)可选 (Optional)描述
options CredentialCreationOptions 用于创建 Credential 的选项。
preventSilentAccess()

当调用 preventSilentAccess() 时,用户代理必须返回对当前设置对象执行禁止静默访问的结果。

注意:这里的意图是来自源的信号,表明用户已经登出。也就是说,在点击“登出”按钮后,站点更新用户的会话信息,并调用 navigator.credentials.preventSilentAccess()。这会设置禁止静默访问标志,意味着下一次用户访问时,凭据将不会自动传递回页面。

注意:此函数以前称为 requireUserMediation(),该名称应被视为已弃用。

当创建 Navigator 对象(navigator)时,用户代理必须创建一个新的 CredentialsContainer 对象,使用 navigator相关 Realm,并将其与 navigator 关联。

2.3.1. CredentialRequestOptions 字典

为了通过 get() 检索 Credential,调用者在 CredentialRequestOptions 对象中指定一些参数。

注意:CredentialRequestOptions 字典是一个扩展点。如果引入了需要选项的新类型凭据,它们的字典类型将被添加到字典中,以便它们可以传递到请求中。请参阅 § 8.2 扩展点

dictionary CredentialRequestOptions {
  CredentialMediationRequirement mediation = "optional";
  DOMString uiMode;
  AbortSignal signal;
};
mediation 类型为 CredentialMediationRequirement,默认为 "optional"

此属性指定给定凭据请求的中介要求。每个枚举值的含义在下面的 CredentialMediationRequirement 中描述。处理详情定义在 § 2.5.1 请求 Credential 中。

uiMode 类型为 DOMString

此属性指定用户代理执行用户中介时,给定凭据请求的用户界面模式。每个值的含义在下面的 CredentialUiMode 中描述。处理详情定义在 § 2.5.1 请求 Credential 中。

signal 类型为 AbortSignal

此属性允许开发者中止正在进行的 get() 操作。已中止的操作可能会正常完成(通常是在操作完成后才收到中止信号),或者以中止原因拒绝。

本规范的早期版本定义了一个布尔成员 unmediated。将其设置为 true 的效果是将 mediation 设置为 "silent",而将其设置为 false 的效果是将 mediation 设置为 "optional"。

unmediated 应被视为已弃用;新代码应改为依赖 mediation

给定 CredentialCreationOptionsCredentialRequestOptionsoptions)的相关凭据接口对象是一组接口对象,收集如下:

注意:此算法使用凭据类型注册表

  1. settings当前设置对象

  2. relevant interface objects 为一个集合

  3. 对于 options 中的每个 optionKeyoptionValue

    1. credentialInterfaceObject 为其选项成员标识符optionKey适当接口对象(基于 settings全局对象)。

    2. 断言:credentialInterfaceObject[[type]] 插槽等于其选项成员标识符optionKey凭据类型

    3. credentialInterfaceObject 追加到 relevant interface objects 中。

  4. 返回 relevant interface objects

如果以下步骤返回 true,则给定 CredentialRequestOptionsoptions)被认为是先验可匹配的 (matchable a priori)
  1. 对于 options相关凭据接口对象中的每个 interface

    1. 如果 interface[[discovery]] 插槽的值不是 "credential store",则返回 false

  2. 返回 true

注意:执行 get(options) 时,仅当提供的 CredentialRequestOptions先验可匹配的时,我们才会返回没有用户中介的凭据。如果请求了任何可能需要从某些外部服务发现的凭据类型(OAuth 令牌、安全密钥认证器等),则将需要用户中介来引导发现过程(通过选择联合身份提供商、BTLE 设备等)。

2.3.2. 中介要求

当通过 get(options)create(options) 发出请求时,开发者可以通过选择适当的 CredentialMediationRequirement 枚举值,为用户中介设置具体的要求。

注意:§ 5 用户中介 节更详细地介绍了该概念,以及它如何影响用户代理处理给定源的单个请求的方式。

enum CredentialMediationRequirement {
  "silent",
  "optional",
  "conditional",
  "required"
};
silent

对于给定的操作,用户中介被抑制。如果操作可以在没有用户参与的情况下执行,那很好。如果需要用户参与,则操作将返回 null,而不是让用户参与。

注意:预期的用法是支持“让我保持登录此网站”场景,其中开发者可能希望在用户应该自动登录时静默获取凭据,但直到用户主动选择登录时,才延迟以登录提示打扰用户。

可选

如果无需用户中介即可为给定操作移交凭据,则会移交。如果需要用户中介,则用户代理将让用户参与决策。

注意:这是 get() 的默认行为,旨在服务于开发者有合理信心认为用户希望开始登录操作的情况。例如,如果用户刚刚点击了“登录”,那么如果需要,他们看到凭据选择器就不会感到惊讶或困惑。

conditional

对于 get(),发现的凭据会在非模态对话框中呈现给用户,并附带请求凭据的的指示。如果用户在对话框之外进行手势操作,对话框将关闭,而不会解析或拒绝 Promise(由 get() 方法返回),也不会导致用户可见的错误情况。如果用户进行选择凭据的手势,则该凭据将返回给调用者。禁止静默访问标志被视为 true,无论其实际值如何:如果发现了适用的凭据,conditional 行为总是涉及某种形式的用户中介

如果没有发现凭据,用户代理可能会提示用户采取行动,具体方式取决于凭据类型(例如插入包含凭据的设备)。无论哪种方式,get() 方法都不得立即解析为 null,以避免向网站泄露缺乏适用凭据的情况。

仅当网站引用的所有凭据接口都已覆盖 isConditionalMediationAvailable() 并返回一个解析为 truePromise 时,网站才能将 conditional 传递给 get() 方法。

对于 create(),如果用户之前已同意创建凭据且用户代理知道它最近调解了一次身份验证,那么 create() 调用可能会在没有额外的突出模态交互的情况下解析。如果用户代理最近没有调解身份验证或者没有获得凭据创建的同意,则该调用必须抛出一个 "NotAllowedError" DOMException

required(必须)

用户代理不会在没有用户中介的情况下移交凭据,即使该源的禁止静默访问标志未设置也是如此。

注意:此要求旨在支持重新身份验证用户切换场景。此外,该要求与特定操作相关联,不会影响该源的禁止静默访问标志。要设置该标志,开发者应调用 preventSilentAccess()

2.3.3. UI 模式

当通过 get(options) 发出请求时,开发者可以通过选择适当的 CredentialUiMode 枚举值来指定所需用户中介模式。

UI Mode 字段没有默认值。当未指定时,[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 方法必须独立考量 CredentialMediationRequirement,以指定用户代理的行为。

注意:用户调解 发生时,这允许调用者区分不同可用的 用户调解 形式。是否显示 UI 取决于请求的 CredentialMediationRequirement 值。并非 CredentialUiMode 的所有值都与所有 CredentialMediationRequirement 值组合都有意义,并且其交互取决于支持该操作的凭据类型的 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 方法。

enum CredentialUiMode {
  "immediate"
};
immediate

在调用 get() 时,用户代理要么向用户显示模态凭据选择对话框,要么操作会立即完成而不提供任何凭据。

这使得可以向用户显示简化的登录 UI,否则网站可以采取替代操作,例如显示其自己的登录页面或继续非登录用户的流程。

如果凭据选择对话框中没有可显示的凭据,则会跳过 用户调解,例如,不会提示用户提供凭据。

注意: 本规范未提供类似于 isConditionalMediationAvailable() 的静态方法来检测 immediate 模式的功能可用性。未来,如果此调解模式扩展到包含其他凭据类型,将需要一种更通用的功能检测方法,能够指示在给定的 CredentialMediationRequirementCredentialUiMode 值组合下,哪些凭据类型受支持。

2.3.3.1. 示例
MegaCorp, Inc. 希望在可能的情况下无缝登录用户。他们可以通过在落地页加载时的某个便捷时刻,为所有未登录用户调用 get() 来实现这一点,并传入设置为 "silent" 的 mediation 成员。这确保了已选择放弃用户调解要求(如 § 5.2 Requiring User Mediation 中所述)的用户能够登录,而未选择此类行为的用户也不会因无缘无故弹出的 凭据选择器 而受到干扰。
window.addEventListener('load', async () => {
  const credentials = await navigator.credentials.get({
    ...,
    mediation: 'silent'
  });
  if (credentials) {
    // Hooray! Let's sign the user in using these credentials!
  }
});
当用户点击“登录”时,MegaCorp, Inc. 希望为他们提供尽可能流畅的体验。如果他们已 选择 在没有 用户调解 的情况下登录,并且用户代理可以明确选择凭据,那就太好了!否则,将显示一个 凭据选择器
document.querySelector('#sign-in').addEventListener('click', async () => {
  const credentials = await navigator.credentials.get({
    ...,
    mediation: 'optional'
  });
  if (credentials) {
    // Hooray! Let's sign the user in using these credentials!
  }
});

注意: MegaCorp, Inc. 也可以完全省略 mediation 成员,因为 "optional" 是其默认值。

MegaCorp, Inc. 希望通过要求用户在采取行动之前进行重新认证来保护敏感操作。即使用户已 选择 在没有 用户调解 的情况下登录,MegaCorp, Inc. 也可以通过使用设置为 "required" 的 mediation 成员调用 get() 来确保用户代理要求进行调解。

注意: 根据浏览器的安全模型或凭据类型,这可能要求用户以某种方式自行进行身份验证,例如在将凭据交给网站之前输入主密码、扫描指纹等。

document.querySelector('#important-form').addEventListener('submit', async () => {
  const credentials = await navigator.credentials.get({
    ...,
    mediation: 'required'
  });
  if (credentials) {
    // Verify that |credentials| enables access, and cancel the submission
    // if it doesn't.
  } else {
    e.preventDefault();
  }
});
MegaCorp, Inc. 希望支持一次登录多个用户账户。为了确保用户有机会选择不同的凭据,MegaCorp, Inc. 可以使用设置为 "required" 的 mediation 成员调用 get(),以确保在点击“添加账户”按钮时凭据不会自动返回。
document.querySelector('#switch-button').addEventListener('click', e => {
  var c = await navigator.credentials.get({
    ...,
    mediation: 'required'
  });
  if (c) {
    // Sign the user in using |c|.
  }
});

2.4. CredentialCreationOptions 字典

为了通过 create() 创建 Credential,调用者需要在 CredentialCreationOptions 对象中指定一些参数。

注意: CredentialCreationOptions 字典是一个扩展点。如果引入新的凭据类型,它们将添加到此字典中,以便可以传递到创建方法中。请参阅 § 8.2 Extension Points 以及本文档中引入的扩展:§ 3.2 The PasswordCredential Interface§ 4.1 The FederatedCredential Interface

dictionary CredentialCreationOptions {
  CredentialMediationRequirement mediation = "optional";
  AbortSignal signal;
};
signal, 类型为 AbortSignal

此属性允许开发者中止正在进行的 create() 操作。已中止的操作可能会正常完成(通常是在操作结束后才收到中止信号时),或者以 中止原因 拒绝。

2.5. 算法

2.5.1. 请求 Credential

请求 Credential 算法接受一个 CredentialRequestOptions (options),并返回一个 Promise,如果能明确获取到凭据,则该 Promise 解析为 Credential;否则,解析为 null

  1. settings当前设置对象

  2. 断言:settings 是一个 安全上下文

  3. documentsettings相关全局对象关联文档

  4. 如果 document 不是 完全活动的,则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException

  5. 如果 options.signal中止,则返回 一个被拒绝的 promise,并带有 options.signal中止原因

  6. interfacesoptions相关凭据接口对象

  7. 如果 interfaces,则返回 一个被拒绝的 promise,并带有 "NotSupportedError" DOMException

  8. 遍历 interfaces 中的每个 interface1

    1. type1interface1[[type]]

    2. 遍历 interfaces 中的每个 interface2

      1. type2interface2[[type]]

      2. 如果 type1 等于 type2,则继续。

      3. 如果 type1同一 get() 请求中允许的类型包含 type2,则返回 一个被拒绝的 promise,并带有 "NotSupportedError" DOMException

  9. 遍历 interfaces 中的每个 interface

    1. 如果 options.mediationconditionalinterface 不支持 conditional 用户调解,则返回 一个被拒绝的 promise,并带有 TypeError

    2. 如果 options.uiModeimmediateinterface 不支持 immediate 用户调解,则返回 一个被拒绝的 promise,并带有 TypeError

    3. 如果 settings活动凭据类型 包含 interface[[type]],则返回 一个被拒绝的 promise,并带有 "NotAllowedError" DOMException

    4. 追加 interface[[type]]settings活动凭据类型 中。

  10. originsettings

  11. sameOriginWithAncestors 为:如果 settings其祖先同源,则为 true,否则为 false

  12. 遍历 options相关凭据接口对象 中的每个 interface

    1. permissioninterface[[type]]获取权限策略

    2. 如果 permission 为 null,则继续。

    3. 如果 document 被允许使用 permission,则返回 一个被拒绝的 promise,并带有 "NotAllowedError" DOMException

  13. p一个新的 promise

  14. 并行中 运行以下步骤:

    1. credentials从凭据存储收集 Credentials 的结果,传入 originoptionssameOriginWithAncestors

    2. 如果 credentials 是一个 异常,则 拒绝 p,并带有 credentials

    3. 如果以下所有陈述均为真,则解析 p 并带有 credentials[0],并跳过剩余步骤

      1. credentials大小 为 1

      2. origin要求用户调解

      3. options先验可匹配的

      4. options.mediation 不为 "required"。

      5. options.mediation 不为 "conditional"。

      这可能是一个错误的模型。如果能支持希望同时接受用户名/密码或 webauthn 类型凭据的网站,而无需强迫那些使用前者且希望保持登录状态的用户进行选择,那就太好了。

    4. 如果 optionsmediation 为 "silent",则 解析 p 并带有 null,并跳过剩余步骤。

    5. result请求用户选择一个 Credential 的结果,传入 optionscredentials

    6. 如果 result 是一个 接口对象

      1. result 设置为执行 result[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 的结果,传入 originoptionssameOriginWithAncestors

        如果该操作抛出一个 异常

        1. e 为抛出的 异常

        2. 在全局对象DOM 操作任务源 上排队一个任务以运行以下子步骤

          1. 拒绝 p,并带有 e

        3. 终止这些子步骤。

    7. 断言:resultnull 或一个 Credential

    8. 如果 result 是一个 Credential,则 解析 p 并带有 result

    9. 如果 resultnulloptions.mediation 不为 conditional,则 解析 p 并带有 result

      注意:如果 options.mediationconditional 且发现了一个 null 凭据,则 promise p 不会解析。

  15. p 做出反应

    1. 遍历 interfaces 中的每个 interface

      1. 移除 interface[[type]]settings活动凭据类型 中。

  16. 返回 p

2.5.2. 从凭据存储收集 Credentials

给定一个 (origin)、一个 CredentialRequestOptions (options) 以及一个布尔值(当且仅当调用上下文为 与其祖先同源 时为 true,否则为 false)(sameOriginWithAncestors),用户代理可以 从凭据存储收集 Credentials,返回存储在用户代理本地且匹配 options 过滤器的 Credential 对象集合。如果不存在此类已知的 Credential 对象,则返回的集合为空。

  1. possible matches 为一个空集合。

  2. 遍历 options相关凭据接口对象 中的每个 interface

    1. r 为执行 interface[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 内部方法的结果,作用于 originoptionssameOriginWithAncestors。如果该操作抛出一个 异常,则重新抛出该异常。

    2. 断言:r 是一个 接口对象 列表。

    3. 遍历 r 中的每个 c

      1. 追加 cpossible matches 中。

  3. 返回 possible matches

2.5.3. 存储 Credential

存储 Credential 算法接受一个 Credential (credential),并返回一个 Promise,该 Promise 在对象持久化到 凭据存储 后解析。

  1. settings当前设置对象

  2. 断言:settings 是一个 安全上下文

  3. 如果 settings相关全局对象关联文档 不是 完全活动的,则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException

  4. sameOriginWithAncestors 为:如果 当前设置对象其祖先同源,则为 true,否则为 false

  5. p一个新的 promise

  6. 如果 settings活动凭据类型 包含 credential[[type]],则返回 一个被拒绝的 promise,并带有 "NotAllowedError" DOMException

  7. 追加 credential[[type]]settings活动凭据类型 中。

  8. 按以下步骤并行运行:

    1. credentialsameOriginWithAncestors 上执行 credential接口对象[[Store]](credential, sameOriginWithAncestors) 内部方法。

      如果该操作抛出一个 异常

      1. e 为抛出的 异常

      2. 在全局对象DOM 操作任务源 上排队一个任务以运行以下子步骤

        1. 拒绝 p,并带有 e

      否则,解析 p 并带有 undefined

  9. p 做出反应

    1. 移除 credential[[type]]settings活动凭据类型 中。

  10. 返回 p

2.5.4. 创建 Credential

创建 Credential 算法接受一个 CredentialCreationOptions (options),并返回一个 Promise,如果能使用提供的选项创建一个 Credential,则该 Promise 解析为该凭据;否则,如果无法创建,则解析为 null。在特殊情况下,Promise 可能会拒绝并抛出相应的异常。

  1. settings当前设置对象

  2. 断言:settings 是一个 安全上下文

  3. globalsettings全局对象

  4. document相关全局对象关联文档

  5. 如果 document 不是 完全活动的,则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException

  6. sameOriginWithAncestors 为:如果 当前设置对象其祖先同源,则为 true,否则为 false

  7. interfacesoptions相关凭据接口对象集合

  8. 如果以下任何陈述为真,则返回 一个被拒绝的 promise,并带有 NotSupportedError

    1. global 没有 关联文档

    2. interfaces大小 大于 1。

      注意: 在未来的某个时候放宽此限制以允许用户代理帮助用户在多种潜在凭据类型中进行选择以支持“注册”用例可能是合理的。但目前,我们通过将字典限制为单个条目来搁置此问题。

  9. 遍历 interfaces 中的每个 interface

    1. permissioninterface[[type]]创建权限策略

    2. 如果 permission 为 null,则继续。

    3. 如果 document 被允许使用 permission,则返回 一个被拒绝的 promise,并带有 "NotAllowedError" DOMException

  10. 如果 options.signal中止,则返回 一个被拒绝的 promise,并带有 options.signal中止原因

  11. typeinterfaces[0] 的 [[type]]

  12. 如果 settings活动凭据类型 包含 type,则返回 一个被拒绝的 promise,并带有 "NotAllowedError" DOMException

  13. 追加 typesettings活动凭据类型 中。

  14. originsettings

  15. p一个新的 promise

  16. 并行运行以下步骤

    1. r 为执行 interfaces[0] 的 [[Create]](origin, options, sameOriginWithAncestors) 内部方法的结果,作用于 originoptionssameOriginWithAncestors

      如果该操作抛出一个 异常

      1. e 为抛出的 异常

      2. 在全局对象DOM 操作任务源 上排队一个任务以运行以下子步骤

        1. 拒绝 p,并带有 e

      3. 终止这些子步骤。

    2. 如果 r 是一个 Credentialnull,则 解析 p 并带有 r,并终止这些子步骤。

    3. 断言:r 是一个算法(如 § 2.2.1.4 [[Create]] internal method 中所定义)。

    4. 在全局对象DOM 操作任务源 上排队一个任务以运行以下子步骤

      1. 解析 p,带有 promise 调用 r 的结果,并给定 global

  17. p 做出反应

    1. 移除 typesettings活动凭据类型 中。

  18. 返回 p

2.5.5. 防止静默访问

防止静默访问 算法接受一个 环境设置对象 (settings),并返回一个 Promise,该 Promise 在 prevent silent access 标志持久化到 凭据存储 后解析。

  1. originsettings

  2. 如果 settings相关全局对象关联文档 不是 完全活动的,则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException

  3. p一个新的 promise

  4. 并行 运行以下步骤

    1. 设置 origin凭据存储 中的 防止静默访问标志

    2. 解析 p 并带有 undefined

  5. 返回 p

3. 密码凭据

无论好坏,许多网站都依赖用户名/密码对作为身份验证机制。PasswordCredential 接口是一种旨在启用此用例的 凭据,它存储用户名和密码,以及可以帮助用户从 凭据选择器 中选择正确账户的元数据。

3.1. 示例

3.1.1. 基于密码的登录

MegaCorp, Inc. 支持密码,可以使用 navigator.credentials.get() 从用户的 凭据存储 中获取用户名/密码对。navigator.credentials .get({ 'password': true }) .then(credential => { if (!credential) { // The user either doesn't have credentials for this site, or // refused to share them. Insert some code here to fall back to // a basic login form. return; } if (credential.type == 'password') { var form = new FormData(); form.append('username_field', credential.id); form.append('password_field', credential.password); var opt = { method: 'POST', body: form, credentials: 'include' // Send cookies. }; fetch('https://example.com/loginEndpoint', opt) .then(function (response) { if (/* |response| indicates a successful login */) { // Record that the credential was effective. See note below. navigator.credentials.store(credential); // Notify the user that sign-in succeeded! Do amazing, signed-in things! // Maybe navigate to a landing page via location.href = // '/signed-in-experience'? } else { // Insert some code here to fall back to a basic login form. } }); } });

或者,网站可以直接将凭据数据复制到 form 中,并对该表单调用 submit()

navigator.credentials
  .get({ 'password': true })
  .then(credential => {
    if (!credential) {
      return; // as above...
    }
    if (credential.type === 'password') {
      document.querySelector('input[name=username_field]').value =
        credential.id;
      document.querySelector('input[name=password_field]').value =
        credential.password;
      document.getElementById('myform').submit();
    }
  });

请注意,前一种方法更受推荐,因为它包含对 store() 的显式调用并保存了凭据。基于 form 的机制依赖于表单提交,这会导航浏览上下文,从而难以确保在登录成功后调用 store()

注意: 用户代理呈现的 凭据选择器 可能允许用户选择实际上未存储在当前源中的凭据。例如,在登录 https://www.example.com 时,它可能会提供来自 https://m.example.com 的凭据(如 § 6.1 Cross-domain credential access 中所述),或者可能允许用户即时创建新凭据。开发者可以通过在凭据成功使用时每次都调用 store() 来妥善处理这种不确定性,即使是在刚刚从 get() 获取凭据之后:如果凭据尚未为该源存储,用户将获得存储的机会。如果它们已存储,则不会提示用户。

3.1.2. 登录后确认

为了确保在登录成功后向用户提供存储新凭据的建议,可以将它们传递给 store()

如果用户通过 fetch() 将凭据提交到登录端点进行登录,我们可以检查响应以确定用户是否成功登录,并据此通知用户代理。给定如下的登录表单<form action="https://example.com/login" method="POST" id="theForm"> <label for="username">Username</label> <input type="text" id="username" name="username" autocomplete="username"> <label for="password">Password</label> <input type="password" id="password" name="password" autocomplete="current-password"> <input type="submit"> </form>

那么开发者可以使用类似以下处理程序来处理表单提交

document.querySelector('#theForm').addEventListener('submit', e => {
    if (window.PasswordCredential) {
      e.preventDefault();

      // Construct a new PasswordCredential from the HTMLFormElement
      // that fired the "submit" event: this will suck up the values of the fields
      // labeled with "username" and "current-password" autocomplete
      // attributes:
      var c = new PasswordCredential(e.target);

      // Fetch the form's action URL, passing that new credential object in
      // as a FormData object. If the response indicates success, tell the user agent
      // so it can ask the user to store the password for future use:
      var opt = {
        method: 'POST',
        body: new FormData(e.target),
        credentials: 'include'  // Send cookies.
      };
      fetch(e.target.action, opt).then(r => {
        if (/* |r| is a "successful" Response */)
          navigator.credentials.store(c);
      });
    }
});

3.1.3. 更改密码

同样的存储机制可以复用于“更改密码”,无需修改:如果用户更改了其凭据,网站可以通知用户代理他们已使用新凭据成功登录。然后,用户代理可以更新其存储的凭据。

MegaCorp Inc. 允许用户通过异步 POST 数据到后端服务器来更改密码。成功执行此操作后,他们可以通过使用新信息调用 store() 来更新用户的凭据。给定如下的密码更改表单
<form action="https://example.com/changePassword" method="POST" id="theForm">
  <input type="hidden" name="username" autocomplete="username" value="user">
  <label for="password">New Password</label>
  <input type="password" id="password" name="password" autocomplete="new-password">
  <input type="submit">
</form>

开发者可以使用类似以下的方式来处理表单提交

document.querySelector('#theForm').addEventListener('submit', e => {
  if (window.PasswordCredential) {
    e.preventDefault();

    // Construct a new PasswordCredential from the HTMLFormElement
    // that fired the "submit" event: this will suck up the values of the fields
    // labeled with "username" and "new-password" autocomplete
    // attributes:
    var c = new PasswordCredential(e.target);

    // Fetch the form's action URL, passing that new credential object in
    // as a FormData object. If the response indicates success, tell the user agent
    // so it can ask the user to store the password for future use:
    var opt = {
      method: 'POST',
      body: new FormData(e.target),
      credentials: 'include'  // Send cookies.
    };
    fetch(e.target.action, opt).then(r => {
      if (/* |r| is a "successful" Response */)
        navigator.credentials.store(c);
    });
  }
});

3.2. PasswordCredential 接口

[Exposed=Window,
 SecureContext]
interface PasswordCredential : Credential {
  constructor(HTMLFormElement form);
  constructor(PasswordCredentialData data);
  readonly attribute USVString password;
};
PasswordCredential includes CredentialUserData;

partial dictionary CredentialRequestOptions {
  boolean password = false;
};
password, 类型为 USVString,只读

此属性表示凭据的密码。

[[type]]

PasswordCredential 接口对象 具有一个名为 [[type]] 的内部槽,其值为 "password"。

[[discovery]]

The PasswordCredential 接口对象 具有一个名为 [[discovery]] 的内部槽,其值为 "credential store"。

PasswordCredential(form)

此构造函数接受一个 HTMLFormElement (form),并运行以下步骤

  1. origin当前设置对象

  2. r 为执行 从 HTMLFormElement 创建 PasswordCredential 的结果,给定 formorigin

  3. 如果 r 是一个 异常,则 抛出 r

    否则,返回 r

PasswordCredential(data)

此构造函数接受一个 PasswordCredentialData (data),并运行以下步骤

  1. r 为执行 从 PasswordCredentialData 创建 PasswordCredential 的结果,作用于 data

  2. 如果 r 是一个 异常,则 抛出 r

    否则,返回 r

PasswordCredential 对象可以通过 navigator.credentials.create() 创建,既可以通过显式传递 PasswordCredentialData 字典,也可以基于 HTMLFormElement可提交元素 的内容创建。

dictionary PasswordCredentialData : CredentialData {
  USVString name;
  USVString iconURL;
  required USVString origin;
  required USVString password;
};

typedef (PasswordCredentialData or HTMLFormElement) PasswordCredentialInit;

partial dictionary CredentialCreationOptions {
  PasswordCredentialInit password;
};

PasswordCredential 对象是 源绑定 的。

PasswordCredential接口对象 继承了 Credential[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 的实现,并定义了其自己的 [[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)[[Create]](origin, options, sameOriginWithAncestors)[[Store]](credential, sameOriginWithAncestors) 的实现。

3.3. 算法

3.3.1. PasswordCredential[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)

[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 接收一个 (origin)、一个 CredentialRequestOptions (options) 以及一个布尔值(当且仅当调用上下文为 与其祖先同源 时为 true,否则为 false)(sameOriginWithAncestors) 被调用。该算法返回来自 凭据存储Credential 对象集合。如果没有可用的匹配 Credential 对象,则返回的集合为空。

如果 sameOriginWithAncestors 不为 true,算法将抛出 NotAllowedError

  1. 断言:options["password"] 存在

  2. 如果 sameOriginWithAncestorsfalse,则抛出 "NotAllowedError" DOMException

    注意: 此限制旨在解决 § 6.4 Origin Confusion 中提出的顾虑。

  3. 如果 options["password"] 不为 true,则返回空集合。

  4. 返回 检索 匹配以下过滤器的 凭据存储 中的凭据的结果

    1. 该凭据是一个 PasswordCredential

    2. 该凭据的 [[origin]]origin同源

3.3.2. PasswordCredential[[Create]](origin, options, sameOriginWithAncestors)

[[Create]](origin, options, sameOriginWithAncestors) 接收一个 (origin)、一个 CredentialCreationOptions (options) 以及一个布尔值(当且仅当调用上下文为 与其祖先同源 时为 true,否则为 false)(sameOriginWithAncestors) 被调用。该算法返回一个 PasswordCredential,如果能创建;否则返回 nullCredentialCreationOptions 字典必须包含一个 password 成员,该成员持有一个 HTMLFormElement 或一个 PasswordCredentialData。如果该成员的值不能用于创建 PasswordCredential,此算法将抛出一个 TypeError 异常

  1. 断言:options["password"] 存在,且 sameOriginWithAncestors 未被使用。

  2. 如果 options["password"] 是一个 HTMLFormElement,则返回执行 从 HTMLFormElement 创建 PasswordCredential 的结果,给定 options["password"] 和 origin。重新抛出任何异常。

  3. 如果 options["password"] 是一个 PasswordCredentialData,则返回执行 从 PasswordCredentialData 创建 PasswordCredential 的结果,给定 options["password"]。重新抛出任何异常。

  4. 抛出一个 TypeError 异常

3.3.3. PasswordCredential[[Store]](credential, sameOriginWithAncestors)

[[Store]](credential, sameOriginWithAncestors) 接收一个 PasswordCredential (credential) 以及一个布尔值(当且仅当调用上下文为 与其祖先同源 时为 true,否则为 false)(sameOriginWithAncestors) 被调用。该算法在 credential 持久化到 凭据存储 后返回 undefined

如果 sameOriginWithAncestors 不为 true,算法将返回 NotAllowedError

  1. 如果 sameOriginWithAncestorsfalse,则抛出 "NotAllowedError" DOMException,且不修改用户代理的 凭据存储

    注意: 此限制旨在解决 § 6.4 Origin Confusion 中提出的顾虑。

  2. 如果用户代理的 凭据存储 包含一个 PasswordCredential (stored),其 id 属性为 credentialid,且其 [[origin]] 槽与 credential[[origin]]同源,则

    1. 如果用户授予了更新凭据的权限(如定义 用户调解 时所讨论),则

      1. 设置 storedpasswordcredentialpassword

      2. 设置 storednamecredentialname

      3. 设置 storediconURLcredentialiconURL

    否则,如果用户授予了存储凭据的权限(如定义 用户调解 时所讨论),则

    1. PasswordCredential 存储在 凭据存储 中,并具有以下属性

      id

      credentialid

      name,

      credentialname

      iconURL

      credentialiconURL

      [[origin]]

      credential[[origin]]

      密码

      credentialpassword

3.3.4. HTMLFormElement 创建 PasswordCredential

HTMLFormElement 创建 PasswordCredential,给定一个 HTMLFormElement (form) 和一个 (origin),运行这些步骤。

注意: § 3.1.2 Post-sign-in Confirmation§ 3.1.3 Change Password 提供了预期用法的示例。

  1. data 为一个新的 PasswordCredentialData 字典。

  2. dataorigin 成员的值设置为 origin 的值。

  3. formData 为在 form 上执行 FormData 构造函数的结果。

  4. elements 为所有 可提交元素 的列表,其 表单所有者form,按 树顺序 排列。

  5. newPasswordObservedfalse

  6. 遍历 elements 中的每个 field,运行以下步骤

    1. 如果 field 没有 autocomplete 属性,则跳至下一个 field

    2. namefieldname 属性的值。

    3. 如果 formDatahas() 方法在 name 上执行时返回 false,则跳至下一个 field

    4. 如果 fieldautocomplete 属性的值包含一个或多个 自动填充详细标记 (tokens),则

      1. 遍历 tokens 中的每个 token

        1. 如果 token 是以下字符串之一的 ASCII 大小写不敏感 匹配项,则运行关联步骤

          "new-password"

          datapassword 成员的值设置为在 name 上执行 formDataget() 方法的结果,并将 newPasswordObserved 设置为 true

          "current-password"

          如果 newPasswordObservedfalse,则将 datapassword 成员的值设置为在 name 上执行 formDataget() 方法的结果。

          注意: 通过检查 newPasswordObserved 是否为 falsenew-password 字段优先于 current-password 字段。

          "photo"

          dataiconURL 成员的值设置为在 name 上执行 formDataget() 方法的结果。

          "name"
          "nickname"

          dataname 成员的值设置为在 name 上执行 formDataget() 方法的结果。

          "username"

          dataid 成员的值设置为在 name 上执行 formDataget() 方法的结果。

  7. c 为执行 从 PasswordCredentialData 创建 PasswordCredential 的结果,作用于 data。如果该操作抛出一个 异常,则重新抛出该异常。

  8. 断言:c 是一个 PasswordCredential

  9. 返回 c

3.3.5. PasswordCredentialData 创建 PasswordCredential

PasswordCredentialData 创建 PasswordCredential,给定一个 PasswordCredentialData (data),运行这些步骤。

  1. c 为一个新的 PasswordCredential 对象。

  2. 如果以下任何项为空字符串,则抛出 TypeError 异常

    • dataid 成员的值

    • dataorigin 成员的值

    • datapassword 成员的值

  3. 设置 c 的属性如下

    密码

    datapassword 成员的值

    id

    dataid 成员的值

    iconURL

    dataiconURL 成员的值

    name

    dataname 成员的值

    [[origin]]

    dataorigin 成员的值。

  4. 返回 c

3.3.6. PasswordCredentialCredentialRequestOptions 匹配

给定一个 CredentialRequestOptions (options),如果 PasswordCredential 应作为 get() 请求的响应可用,则以下算法返回 "Matches",否则返回 "Does Not Match"。

  1. 如果 options 具有一个其值为 truepassword 成员,则返回 "Matches"。

  2. 返回 "Does Not Match"。

4. 联合凭据

4.1. FederatedCredential 接口

[Exposed=Window,
 SecureContext]
interface FederatedCredential : Credential {
  constructor(FederatedCredentialInit data);
  readonly attribute USVString provider;
  readonly attribute DOMString? protocol;
};
FederatedCredential includes CredentialUserData;

dictionary FederatedCredentialRequestOptions {
  sequence<USVString> providers;
  sequence<DOMString> protocols;
};

partial dictionary CredentialRequestOptions {
  FederatedCredentialRequestOptions federated;
};
provider, 类型为 USVString,只读

该凭据的联合身份提供商。关于有效格式的详细信息,请参阅 § 4.1.1 Identifying Providers

protocol, 类型为 DOMString,只读,可为空

凭据的联合身份提供商协议(例如“openidconnect”)。如果值为 null,则可以从 provider 中推断出协议。

[[type]]

FederatedCredential 接口对象有一个名为 [[type]] 的内部槽,其值为 "federated"。

[[discovery]]

FederatedCredential 接口对象有一个名为 [[discovery]] 的内部槽,其值为 "credential store"(凭据存储)。

FederatedCredential(data)

此构造函数接受一个 FederatedCredentialInit (data),并执行以下步骤

  1. r 为在 data 上执行 从 FederatedCredentialInit 创建 FederatedCredential 的结果。如果抛出了 异常,则重新抛出该异常。

  2. 返回 r

FederatedCredential 对象可以通过将 FederatedCredentialInit 字典传递给 navigator.credentials.create() 来创建。

dictionary FederatedCredentialInit : CredentialData {
  USVString name;
  USVString iconURL;
  required USVString origin;
  required USVString provider;
  DOMString protocol;
};

partial dictionary CredentialCreationOptions {
  FederatedCredentialInit federated;
};

FederatedCredential 对象是 源绑定的

FederatedCredential接口对象继承了 Credential[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 的实现,并定义了其自身对 [[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)[[Create]](origin, options, sameOriginWithAncestors)[[Store]](credential, sameOriginWithAncestors) 的实现。

注意:如果将来我们让用户代理代表用户获取身份验证令牌,我们可以通过构建 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 的实现来实现。

4.1.1. 识别提供商

每个站点在引用特定的联合身份提供商时,都应该使用相同的标识符。例如,Facebook 登录不应被称为“Facebook”、“Facebook 登录”、“FB”、“FBL”、“Facebook.com”等。它应该有一个每个人都可以使用的规范标识符,因为一致的识别使用户代理能够提供帮助。

为了保持一致性,传入本文档定义的 API(例如 FederatedCredentialRequestOptionsproviders 数组,或 FederatedCredentialprovider 属性)的联合,必须通过提供商用于登录的源的 ASCII 序列化进行标识。也就是说,Facebook 应表示为 https://#,Google 应表示为 https://#

这种的序列化不包括末尾的 U+002F 斜杠("/"),但用户代理应该静默地接受它们:https://#/ 显然被视为与 https://# 相同。

4.2. 算法

4.2.1. FederatedCredential[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)

[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 使用origin)、CredentialRequestOptionsoptions)以及一个布尔值(当且仅当调用上下文与其祖先同源时为 true)来调用(sameOriginWithAncestors)。该算法从凭据存储中返回一组 Credential 对象。如果没有匹配的 Credential 对象可用,则返回的集合为空。

  1. 断言:options["federated"] 存在

  2. 如果 sameOriginWithAncestorsfalse,则抛出 "NotAllowedError" DOMException

    注意: 此限制旨在解决 § 6.4 Origin Confusion 中提出的顾虑。

  3. 如果 options["federated"] 不为 true,则返回空集。

  4. 返回从凭据存储检索匹配以下过滤器的凭据的结果

    1. 凭据是 FederatedCredential

    2. 凭据的 [[origin]]origin 同源

    3. 如果 options["federated"]["providers"] 存在,则其值包含该凭据的 provider

    4. 如果 options["federated"]["protocols"] 存在,则其值包含该凭据的 protocol

4.2.2. FederatedCredential[[Create]](origin, options, sameOriginWithAncestors)

[[Create]](origin, options, sameOriginWithAncestors) 使用origin)、CredentialCreationOptionsoptions)以及一个布尔值(当且仅当调用上下文与其祖先同源时为 true)来调用(sameOriginWithAncestors)。该算法返回一个 FederatedCredential(如果可以创建),否则返回 null,或者在特殊情况下抛出异常

  1. 断言:options["federated"] 存在,且 sameOriginWithAncestors 未被使用。

  2. options["federated"] 的 origin 成员的值设置为 origin 的值。

  3. 返回给定 options["federated"] 执行 从 FederatedCredentialInit 创建 FederatedCredential 的结果。如果该操作抛出了异常,则重新抛出该异常。

4.2.3. FederatedCredential[[Store]](credential, sameOriginWithAncestors)

[[Store]](credential, sameOriginWithAncestors) 使用 FederatedCredentialcredential)和一个布尔值(当且仅当调用上下文与其祖先同源时为 true)来调用(sameOriginWithAncestors)。一旦 credential 被持久化到凭据存储,该算法将返回 undefined

如果 sameOriginWithAncestors 不为 true,算法将返回 NotAllowedError

  1. 如果 sameOriginWithAncestorsfalse,则抛出 "NotAllowedError" DOMException,且不更改用户代理的凭据存储

    注意: 此限制旨在解决 § 6.4 Origin Confusion 中提出的顾虑。

  2. 如果用户代理的凭据存储包含一个 FederatedCredential,其 id 属性为 credentialid,且其 [[origin]] 槽与 credential[[origin]] 同源,且其 providercredentialprovider,则返回。

  3. 如果用户授予了存储凭据的权限(如在定义用户中介时所述),则将 FederatedCredential 存储到凭据存储中,并具有以下属性:

    id

    credentialid

    name,

    credentialname

    iconURL

    credentialiconURL

    [[origin]]

    credential[[origin]]

    provider

    credentialprovider

    protocol

    credentialprotocol

4.2.4. FederatedCredentialInit 创建 FederatedCredential

为了从 FederatedCredentialInit 创建 FederatedCredential,给定一个 FederatedCredentialInit (init),执行以下步骤。

  1. c 为一个新的 FederatedCredential 对象。

  2. 如果以下任一属性为空字符串,则抛出 TypeError 异常

  3. 设置 c 的属性如下

    id

    init.id 的值

    provider

    init.provider 的值

    iconURL

    init.iconURL 的值

    name

    init.name 的值

    [[origin]]

    init.origin 的值。

  4. 返回 c

5. 用户中介

通过 API 将凭据信息暴露给 Web 对用户隐私有许多潜在影响。因此,用户代理必须在许多情况下让用户参与,以确保他们清楚地了解正在发生的事情,以及他们的凭据正在与谁共享。

如果某个特定操作是在获得用户的明确同意后进行的,我们称之为用户中介。例如,同意可以通过用户与凭据选择器界面的直接交互来表达。通常,用户中介的操作将涉及向用户呈现某种 UI,并要求他们做出决定。

如果操作是在没有明确用户同意的情况下静默进行的,则该操作是未中介的。例如,如果用户将浏览器配置为向特定来源授予持久性凭据访问权限,则无需向用户呈现要求做出决定的 UI 即可提供凭据。

在此,我们将阐述适用于所有凭据类型的一些要求,但请注意,用户代理(处于协助用户的特权位置)仍有很大的余地。此外,特定的凭据类型可能具有不同于此处更通用要求的特定要求。

5.1. 存储和更新凭据

凭据信息是敏感数据,用户必须保持对该信息存储的控制。例如,无意中的凭据存储可能会意外地将用户在特定设备上的本地配置文件与特定的在线身份链接起来。为了降低这种风险

  1. 在没有用户中介的情况下,不应存储或更新凭据信息。例如,用户代理可以在每次调用 store() 时向用户显示“保存此凭据?”对话框。

    如果用户代理选择以“始终保存密码”选项的形式提供持久的同意授权,则可以推断出用户同意(尽管我们建议用户代理应倾向于更窄范围的选项:例如“始终保存_生成的_密码”,或“始终保存此站点的密码”)。

  2. 当存储凭据时,用户代理应通知用户。这可以采取地址栏中的图标或类似位置的形式。

  3. 用户代理必须允许用户手动删除已存储的凭据。此功能可以实现为设置页面,或通过与上述通知的交互来实现。

5.2. 要求用户中介

默认情况下,所有都需要用户中介,因为凭据存储中的相关防止静默访问标志被设置为 true。用户可以选择向来源授予持久的凭据访问权限(例如以“保持登录此站点”选项的形式),这将把此标志设置为 false。在这种情况下,用户将始终登录到该站点,这从可用性和便利性的角度来看是可取的,但可能会产生意想不到的后果(例如,考虑一个在设备间同步此标志状态的用户代理)。

为了降低这种风险

  1. 用户代理必须允许用户为特定来源或所有来源要求用户中介。此功能可以实现为覆盖每个来源的防止静默访问标志并将其返回为 false 的全局开关,或者通过针对特定来源(或特定来源上的特定凭据)的更细粒度的设置来实现。

  2. 在没有用户中介的情况下,用户代理不得将防止静默访问标志设置为 false。例如,§ 5.3 凭据选择中描述的凭据选择器可以包含一个复选框,用户可以切换该复选框以将凭据标记为在来源无需中介即可使用,或者用户代理可以为其凭据管理器设置一个引导流程,询问用户的默认设置。

  3. 当向来源提供凭据时,用户代理必须通知用户。这可以采取地址栏中的图标或类似位置的形式。

  4. 如果用户清除了来源的浏览数据(cookie、localStorage 等),用户代理必须将该来源的防止静默访问标志设置为 true

5.3. 凭据选择

在响应需要用户中介的来源上的 get() 调用时,用户代理必须请求用户共享凭据信息的许可。这应采取凭据选择器的形式,该选择器向用户展示可在站点上使用的凭据列表,允许他们选择一个提供给网站,或完全中止请求。

选择器的用户界面应以与网站可以生成的 UI 区分开来的方式实现。例如,选择器可能会以某种无法伪造的方式覆盖用户代理的 UI。

选择器的用户界面必须包含请求凭据的来源的指示。

选择器的用户界面应包含与请求凭据的来源关联的所有 Credential 对象。

为了增强此类选择器的效用,用户代理可以在内部将除本文档中指定的属性之外的信息与每个 Credential 对象关联起来。例如,网站图标可以帮助区分身份提供商等。存储的任何附加信息不得直接暴露给 Web。

选择器的行为在此处未定义:鼓励用户代理尝试各种 UI 处理方式,以教育用户了解其身份验证选项,并引导他们完成选择凭据的过程。话虽如此,选择器的接口如下

给定 CredentialRequestOptions (options) 以及来自凭据存储的一组 Credential 对象(本地发现的凭据),用户代理可以请求用户选择凭据

如果用户选择不与站点共享凭据,此算法将返回 null;如果用户选择了特定凭据,则返回 Credential 对象;如果用户选择了凭据类型,则返回 Credential 接口对象

选择器界面向用户显示本地发现的凭据列表似乎是合理的,或许类似这种非常规的模拟

A mockup of what a chooser might look like.

如果提供的 options 不是先验可匹配的,那么选择器界面列出不在显式凭据列表覆盖范围内的 options相关凭据接口对象可能也是合理的。例如,如果站点接受 WebAuthn 风格的验证器,那么“安全密钥”可能会以相应的图标出现在选择器列表中。

另外,请注意,在某些情况下,用户代理可能会完全跳过选择器。例如,如果唯一的相关凭据接口对象本身需要用户交互,则用户代理可以直接返回该接口,并依赖其内部中介流程来获取用户同意。

6. 安全注意事项

以下部分代表了各种安全和隐私考虑的指南。个别凭据类型可以执行这些指南的更严格或更宽松的版本。

6.1. 跨域凭据访问

凭据是敏感信息,用户代理在确定何时可以安全地与网站共享凭据时需要谨慎行事。最安全的选择是将凭据共享限制在保存它们的精确来源上。然而,这对 Web 来说可能太严格了:考虑将功能划分为子域的站点,如 example.comadmin.example.com

作为不干扰用户和保护其凭据之间的妥协,用户代理

  1. 不得在方案组件代表安全性降低的来源之间共享凭据。也就是说,允许在 http://example.com/ 上保存的凭据可用于 https://example.com/(以鼓励开发人员迁移到安全传输)可能是合理的,但反之则很危险。

  2. 可以使用公共后缀列表 [PSL],通过比较凭据的 [[origin]]可注册域与调用 get() 所在的来源,来确定凭据的有效范围。也就是说:在 https://admin.example.com/https://example.com/ 上保存的凭据,当从 https://www.example.com/ 调用 get() 时,可能会提供给用户,反之亦然。

  3. 如果凭据的来源与调用来源不完全匹配,在没有用户中介的情况下,不得响应 get() 向来源提供凭据。也就是说,https://example.comCredential 对象不会直接返回给 https://www.example.com,但可以通过选择器提供给用户。

6.2. 凭据泄露

我们建议开发人员采取一些预防措施,通过设置合理的限制数据发送端点的内容安全策略 [CSP],来降低跨站脚本攻击可能导致用户帐户被持久访问的风险。特别是,开发人员应确保在页面的策略中显式或隐式设置以下指令

  • script-srcobject-src 都限制了页面上的脚本执行,使得跨站脚本攻击成功的可能性降低。如果站点正在填充 form 元素,也应设置 form-action 指令。

  • connect-src 限制了 fetch() 可以提交数据的来源(这降低了凭据被泄露到 evil.com 的风险)。

  • child-src 限制了页面中可以嵌入的嵌套浏览上下文,使得注入恶意 postMessage() 目标更加困难。[HTML]

当然,开发人员还应适当地转义输入和输出,并考虑使用其他防御层,例如子资源完整性 [SRI],以进一步降低风险。

在定义特定凭据类型时,特定凭据类型应适当考虑凭据数据在网上传输的方式。例如,定义仅限于同源端点的传输机制可能是合理的。

6.3. 不安全站点

用户代理不得将此处定义的 API 暴露给非安全上下文的环境。用户代理可能会实现自动填充机制,将用户凭据存储并填充到非潜在可信 URL 上的登录表单中,但这些站点不能被信任与凭据管理器进行任何有意义的交互,并且这些站点不得访问存储在安全上下文中的凭据。

6.4. 来源混淆

如果框架页面可以访问此处定义的 API,则可能会诱导用户授予对除顶级浏览上下文以外的来源的凭据访问权限,而这是用户唯一能够合理理解的安全来源。

本文档将凭据管理 API 暴露给这些上下文,因为如果用户代理投入足够的思考并将上下文置于其 UI 中,某些凭据类型可能很容易实现。

然而,特定的凭据类型在这些上下文中暴露将会有风险。这些凭据类型通过其 [[Create]](origin, options, sameOriginWithAncestors)[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)[[Store]](credential, sameOriginWithAncestors) 方法中的检查进行限制(视情况而定)。

例如,PasswordCredential[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 方法如果在 Worker 或非顶级浏览上下文中调用,将立即返回空集。

6.5. 登出

如果用户已选择自动登录网站(如§ 5.2 要求用户中介中所述),则用户代理将在来源请求时随时向其提供凭据。网站可以通过调用 CredentialsContainerpreventSilentAccess() 方法来指示用户代理抑制此行为,这将关闭特定来源的自动登录。

用户代理依赖于网站执行正确的操作;一个疏忽(或恶意)的网站可能只是忽略了调用此方法,导致用户代理继续提供凭据,违背了用户的明显意图。这比用户点击“登出”时站点未清除用户凭据的现状稍微糟糕一些,因为用户代理成为了身份验证的共犯。

用户必须对此行为有一定的控制权。如§ 5.2 要求用户中介中所述,清除来源的 cookie 也将重置该来源的防止静默访问标志(在凭据存储中)为 true。此外,用户代理应提供某种 UI 辅助功能,以禁用特定来源的自动登录。例如,这可以与向来源提供凭据的通知挂钩。

7. 隐私考虑

7.1. 时间攻击

如果用户没有某个来源的凭据,则对 get() 的调用将非常快速地完成。恶意网站可以区分没有凭据的用户和有凭据但选择不共享它们的用户。

用户代理还应限制凭据请求的频率。页面在短时间内请求多次凭据几乎肯定是滥用行为。

7.2. 选择器泄露

如果用户代理的凭据选择器显示由来源提供的图像(例如,如果 Credential 显示网站的图标),那么请求这些图像时不得直接与实例化选择器绑定,以避免泄露选择器的使用情况。一种选择是在保存或更新 Credential 时在后台获取图像,并将其缓存,生命周期与 Credential 相同。

必须使用凭据模式设置为 "omit"、服务工作线程模式设置为 "none"、客户端设置为 null发起者设置为空字符串,以及目标设置为 "subresource" 来获取这些图像。

此外,如果用户代理允许用户更改与凭据关联的名称或图标,则对数据的更改不应暴露给网站(例如,考虑一个用户将某个来源的两个凭据命名为“我的假帐户”和“我的真帐户”的情况)。

7.3. 本地存储的数据

此 API 为提供了与用户配置文件一起持久存储数据的能力。由于大多数用户代理对待凭据数据的方式与“浏览数据”(cookie 等)不同,这可能会产生令用户意外的副作用,因为他们可能认为在清除 cookie 时已经擦除了来源的所有痕迹。

用户代理应提供 UI,向用户明确说明为来源存储了凭据数据,并应方便用户在不再需要保留数据时删除此类数据。

8. 实现考虑

本节是非规范性的。

8.1. 网站作者

在此处添加关于何时以及如何使用该 API 的想法,特别是关于 mediation[w3c/webappsec Issue #290]

描述通过 fetch() 结合 FormData 正文提交凭据的编码限制。

当为给定的凭据类型执行特性检测时,建议开发人员验证相关的 Credential 专业化是否存在,而不是依赖于 navigator.credentials 的存在。后者验证 API 本身的存在,但不能确保站点所需的特定类型的凭据受支持。例如,如果站点需要密码,则检查 if (window.PasswordCredential) 是最有效的支持验证。

8.2. 扩展点

本文档提供了一个通用的、高级的 API,旨在通过特定的凭据类型进行扩展,以满足特定的身份验证需求。这样做希望是简单的

  1. 定义一个继承自 Credential 的新接口

    [Exposed=Window,
     SecureContext]
    interface ExampleCredential : Credential {
      // Definition goes here.
    };
    
  2. ExampleCredential接口对象上定义适当的 [[Create]](origin, options, sameOriginWithAncestors)[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)[[Store]](credential, sameOriginWithAncestors) 方法。[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 适用于永远有效且因此可以直接从凭据存储中复制出的凭据,而 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 适用于需要从凭据源重新生成的凭据

    建议像 PublicKeyCredential[[Create]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 操作中的长运行操作使用 options.signal 以允许开发人员中止该操作。有关详细说明,请参阅 DOM § 3.3 在 API 中使用 AbortController 和 AbortSignal 对象

    ExampleCredential[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 内部方法使用origin)、CredentialRequestOptions 对象(options)以及一个布尔值(当且仅当调用上下文与其祖先同源时为 true)来调用。该算法返回匹配所提供选项的一组 Credential 对象。如果没有匹配的 Credential 对象可用,则返回的集合为空。
    1. 断言:options[example] 存在。

    2. 如果 options[example] 不为真,则返回空集。

    3. 对于凭据存储中的每个凭据

      1. ...

  3. 定义 ExampleCredential 接口对象[[type]] 槽的值

    ExampleCredential 接口对象有一个名为 [[type]] 的内部槽,其值为字符串 "example"。
  4. 定义 ExampleCredential 接口对象[[discovery]] 槽的值

    ExampleCredential 接口对象有一个名为 [[discovery]] 的内部槽,其值为 "credential store"。
  5. 用新凭据类型响应 get() 所需的选项扩展 CredentialRequestOptions

    dictionary ExampleCredentialRequestOptions {
      // Definition goes here.
    };
    
    partial dictionary CredentialRequestOptions {
      ExampleCredentialRequestOptions example;
    };
    
  6. 用新凭据类型在响应 create() 时创建 Credential 对象所需的数据扩展 CredentialCreationOptions

    dictionary ExampleCredentialInit {
      // Definition goes here.
    };
    
    partial dictionary CredentialCreationOptions {
      ExampleCredentialInit example;
    };
    
  7. 如果新凭据类型支持 conditional 用户中介,则定义 ExampleCredential/isConditionalMediationAvailable() 以返回true 决议的 Promise

  8. 按照 § 2.1.2.1 注册条目要求和更新流程中的程序,为新的 "example" 凭据类型及其对应的条目添加到凭据类型注册表

    注意:凭据类型选项字典的选项成员标识符CredentialCreationOptionsCredentialRequestOptions 中必须相同,并且应与 Credential 接口对象[[type]] 槽中的凭据类型值相同。

您可能还会发现新的原语是必要的。例如,您可能希望在某种复杂的、多因素登录过程中返回许多 Credential 对象,而不是只有一个。这可以通过向 CredentialsContainer 添加一个返回 sequence<Credential>getAll() 方法,并定义处理请求不同类型凭据的合理机制,以通用方式实现。

对于任何此类扩展,我们建议咨询 public-webappsec@ 以获得咨询和审查。

8.3. 浏览器扩展

理想情况下,实现某种扩展系统的用户代理将允许第三方挂接到这些 API 端点,以便以用户代理可以通过这种指令性方法改进自身相同的方式,改进第三方凭据管理软件的行为。

这可以从用户代理中介的复杂新 API,到仅仅允许扩展覆盖 get()store() 端点以用于其自身目的,范围各不相同。

9. 未来工作

本节是非规范性的。

此处定义的 API 仅做了最低限度的努力来将用户代理的凭据管理器暴露给 Web,并允许 Web 帮助这些凭据管理器理解何时使用了联合身份提供商。下一个合乎逻辑的步骤将沿着类似 [WEB-LOGIN](以及在某种程度上 Mozilla 的 BrowserID [BROWSERID])文档中勾勒的方向进行。

用户代理处于能够有效中介用户、身份提供商和网站之间关系的独特位置。如果用户代理能够消除与典型身份验证流程相关的一些风险和混乱,用户将处于比今天好得多的位置。

暴露此信息的一种自然方式可能是扩展 FederatedCredential 接口,添加身份验证令牌等属性,并可能添加某种声明提供商支持的身份验证类型的清单格式属性。

此处描述的 API 旨在具有足够的扩展性,以支持需要用户交互的用例,例如与请求凭据的网站以外的网站交互。我们希望我们所确定的基于 Promise 的系统足够可扩展,以支持这些类型的异步流(可能需要多个浏览上下文之间的某种交互,例如 idp.com 上的中介活动可能会决议返回给 rp.com 的 Promise)或设备与用户代理之间(例如 [WEBAUTHN])在未来交互,而无需从头重新设计 API。

小步快跑。

索引

本规范定义的术语

  • id
  • "immediate"(立即),在 § 2.3.3
  • immediate(立即),在 § 2.3.3
  • isConditionalMediationAvailable(),在 § 2.2
  • 先验可匹配,在 § 2.3.1
  • mediation(中介)
  • 修改凭据,在 § 2.1
  • name
  • "optional"(可选),在 § 2.3.2
  • optional(可选),在 § 2.3.2
  • 选项成员标识符,在 § 2.1.2
  • [[origin]],在 § 2.2
  • origin
  • 源绑定,在 § 2.2
  • 密码
  • PasswordCredential,在 § 3.2
  • PasswordCredential(data),在 § 3.2
  • PasswordCredentialData,在 § 3.2
  • PasswordCredential(form),在 § 3.2
  • PasswordCredentialInit,在 § 3.2
  • 防止静默访问,在 § 2.5.5
  • preventSilentAccess(),在 § 2.3
  • 防止静默访问标志,在 § 2.1
  • protocol
  • protocols(协议),在 § 4.1
  • provider
  • providers(提供商),在 § 4.1
  • 相关凭据接口对象,在 § 2.3.1
  • remote(远程),在 § 2.2
  • 请求凭据,在 § 2.5.1
  • "required"(必须),在 § 2.3.2
  • required(必须),在 § 2.3.2
  • 要求用户中介,在 § 2.1
  • 检索凭据列表,在 § 2.1
  • 与其祖先同源,在 § 2.1.1.1
  • 信号 (signal)
  • "silent"(静默),在 § 2.3.2
  • silent(静默),在 § 2.3.2
  • store(),在 § 2.3
  • 存储凭据,在 § 2.5.3
  • 存储凭据,在 § 2.1
  • store(credential),在 § 2.3
  • [[Store]](credential, sameOriginWithAncestors)
  • [[type]],在 § 2.2
  • type(类型),在 § 2.2
  • 同一 get() 请求中允许的类型,在 § 2.1.2
  • uiMode,在 § 2.3.1
  • user mediated(用户中介的),在 § 5
  • user mediation(用户中介),在 § 5
  • 通过引用定义的术语

    引用

    规范性引用

    [CSP]
    Mike West; Antonio Sartori. 内容安全策略第 3 级. 2026年4月1日. WD. URL: https://w3org.cn/TR/CSP3/
    [DIGITAL-CREDENTIALS]
    Marcos Cáceres; Sam Goto. 数字凭据. URL: https://wicg.github.io/digital-credentials/
    [DOM]
    Anne van Kesteren. DOM 标准. Living Standard. URL: https://dom.spec.whatwg.org/
    [FEDCM]
    Nicolas Pena Moreno. 联合凭据管理 API. 2024年8月20日. FPWD. URL: https://w3org.cn/TR/fedcm-1/
    [FETCH]
    Anne van Kesteren. 提取标准 (Fetch Standard). 生活标准. URL: https://fetch.spec.whatwg.org/
    [HTML]
    Anne van Kesteren; et al. HTML 标准. Living Standard. URL: https://html.whatwg.cn/multipage/
    [INFRA]
    Anne van Kesteren; Domenic Denicola. Infra 标准. Living Standard. URL: https://infra.spec.whatwg.org/
    [PERMISSIONS]
    Marcos Caceres; Mike Taylor. Permissions (权限). 2025年10月6日. WD. URL: https://w3org.cn/TR/permissions/
    [PROMISES-GUIDE]
    Domenic Denicola. 编写使用 Promise 的规范. 2018年11月9日. TAG Finding. URL: https://w3org.cn/2001/tag/doc/promises-guide
    [PSL]
    公共后缀列表. URL: https://publicsuffix.org/
    [SECURE-CONTEXTS]
    Mike West. 安全上下文. 2023 年 11 月 10 日. CRD. URL: https://w3org.cn/TR/secure-contexts/
    [WEB-OTP]
    WebOTP API. Draft Community Group Report. URL: https://wicg.github.io/web-otp/
    [WEBAUTHN-3]
    Michael Jones; et al. Web 身份验证:用于访问公钥凭据的 API - 第 3 级. 2026年1月13日. CR. URL: https://w3org.cn/TR/webauthn-3/
    [WEBIDL]
    Edgar Chen; Timothy Gu. Web IDL 标准. Living Standard. URL: https://webidl.spec.whatwg.org/
    [XHR]
    Anne van Kesteren. XMLHttpRequest 标准. Living Standard. URL: https://xhr.spec.whatwg.org/

    参考资料

    [BROWSERID]
    Ben Adida; et al. BrowserID. 2013年2月26日. URL: https://github.com/mozilla/id-specs/blob/prod/browserid/index.md
    [SRI]
    Frederik Braun. 子资源完整性. 2026年3月20日. WD. URL: https://w3org.cn/TR/sri-2/
    [WEB-LOGIN]
    Jason Denizac; Robin Berjon; Anne van Kesteren. web-login. URL: https://github.com/jden/web-login
    [WEBAUTHN]
    Dirk Balfanz; et al. Web 身份验证:用于访问公钥凭据的 API 第 1 级. 2019年3月4日. REC. URL: https://w3org.cn/TR/webauthn-1/
    [XMLHTTPREQUEST]
    Anne van Kesteren; et al. XMLHttpRequest 第 1 级. 2016年10月6日. NOTE. URL: https://w3org.cn/TR/XMLHttpRequest/

    IDL 索引

    [Exposed=Window, SecureContext]
    interface Credential {
      readonly attribute USVString id;
      readonly attribute DOMString type;
      static Promise<boolean> isConditionalMediationAvailable();
    };
    
    [SecureContext]
    interface mixin CredentialUserData {
      readonly attribute USVString name;
      readonly attribute USVString iconURL;
    };
    
    partial interface Navigator {
      [SecureContext, SameObject] readonly attribute CredentialsContainer credentials;
    };
    
    [Exposed=Window, SecureContext]
    interface CredentialsContainer {
      Promise<Credential?> get(optional CredentialRequestOptions options = {});
      Promise<undefined> store(Credential credential);
      Promise<Credential?> create(optional CredentialCreationOptions options = {});
      Promise<undefined> preventSilentAccess();
    };
    
    dictionary CredentialData {
      required USVString id;
    };
    
    dictionary CredentialRequestOptions {
      CredentialMediationRequirement mediation = "optional";
      DOMString uiMode;
      AbortSignal signal;
    };
    
    enum CredentialMediationRequirement {
      "silent",
      "optional",
      "conditional",
      "required"
    };
    
    enum CredentialUiMode {
      "immediate"
    };
    
    dictionary CredentialCreationOptions {
      CredentialMediationRequirement mediation = "optional";
      AbortSignal signal;
    };
    
    [Exposed=Window,
     SecureContext]
    interface PasswordCredential : Credential {
      constructor(HTMLFormElement form);
      constructor(PasswordCredentialData data);
      readonly attribute USVString password;
    };
    PasswordCredential includes CredentialUserData;
    
    partial dictionary CredentialRequestOptions {
      boolean password = false;
    };
    
    dictionary PasswordCredentialData : CredentialData {
      USVString name;
      USVString iconURL;
      required USVString origin;
      required USVString password;
    };
    
    typedef (PasswordCredentialData or HTMLFormElement) PasswordCredentialInit;
    
    partial dictionary CredentialCreationOptions {
      PasswordCredentialInit password;
    };
    
    [Exposed=Window,
     SecureContext]
    interface FederatedCredential : Credential {
      constructor(FederatedCredentialInit data);
      readonly attribute USVString provider;
      readonly attribute DOMString? protocol;
    };
    FederatedCredential includes CredentialUserData;
    
    dictionary FederatedCredentialRequestOptions {
      sequence<USVString> providers;
      sequence<DOMString> protocols;
    };
    
    partial dictionary CredentialRequestOptions {
      FederatedCredentialRequestOptions federated;
    };
    
    dictionary FederatedCredentialInit : CredentialData {
      USVString name;
      USVString iconURL;
      required USVString origin;
      required USVString provider;
      DOMString protocol;
    };
    
    partial dictionary CredentialCreationOptions {
      FederatedCredentialInit federated;
    };
    
    

    问题索引

    与 Tobie/Dominic 讨论关于接口对象的内容,在此处以及 § 2.5.1 请求凭据等部分中。我不确定术语是否正确。接口原型对象,也许?
    这可能是错误的模型。如果能支持一个希望接受用户名/密码或 WebAuthn 风格凭据的站点,同时不强迫使用前者并希望保持登录的用户使用选择器,那就太好了。
    在此处添加关于何时以及如何使用该 API 的想法,特别是关于 mediation[w3c/webappsec Issue #290]
    描述通过 fetch() 结合 FormData 正文提交凭据的编码限制。
    MDN

    Credential/id

    在所有当前引擎中。

    Firefox60+Safari13+Chrome51+
    Opera?Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    Credential/type

    在所有当前引擎中。

    Firefox60+Safari13+Chrome51+
    Opera?Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    凭据 (Credential)

    在所有当前引擎中。

    Firefox60+Safari13+Chrome51+
    Opera?Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    CredentialsContainer/create

    在所有当前引擎中。

    Firefox60+Safari13+Chrome60+
    Opera?Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    CredentialsContainer/get

    在所有当前引擎中。

    Firefox60+Safari13+Chrome51+
    Opera?Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    CredentialsContainer/preventSilentAccess

    在所有当前引擎中。

    Firefox60+Safari13+Chrome60+
    Opera?Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    CredentialsContainer/store

    在所有当前引擎中。

    Firefox60+Safari13+Chrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    CredentialsContainer

    在所有当前引擎中。

    Firefox60+Safari13+Chrome51+
    Opera?Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    FederatedCredential/FederatedCredential

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    FederatedCredential/protocol

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    FederatedCredential/provider

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    FederatedCredential

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    Navigator/credentials

    在所有当前引擎中。

    Firefox60+Safari13+Chrome51+
    Opera?Edge79+
    Edge (旧版)18IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PasswordCredential/PasswordCredential

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PasswordCredential/iconURL

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PasswordCredential/name

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PasswordCredential/password

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome60+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
    MDN

    PasswordCredential

    仅在一种当前的引擎中可用。

    FirefoxSafariChrome51+
    Opera?Edge79+
    Edge (旧版)?IE
    Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?