凭证管理 一级

W3C 工作草案,

关于本文档的更多详情
此版本:
https://www.w3.org/TR/2026/WD-credential-management-1-20260213/
最新发布版本:
https://www.w3.org/TR/credential-management-1/
编辑草案:
https://w3c.github.io/webappsec-credential-management/
以往版本:
历史记录:
https://www.w3.org/standards/history/credential-management-1/
反馈:
public-webappsec@w3.org 主题为 “[credential-management] … 消息主题 …” (存档)
GitHub
编辑:
(Google Inc.)
(Apple Inc.)
前编辑:
(Google Inc.)
(Google Inc.)
参与:
提交问题 (开放的问题)

摘要

本规范描述了一个命令式 API,使网站能够向用户代理请求用户的凭证,并帮助用户代理正确地存储用户凭证以备将来使用。

本文档状态

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

本文件由 Web 应用安全工作组 作为工作草案发布,使用推荐轨道。本文件旨在成为一项 W3C 推荐。

已归档)公共邮件列表 public-webappsec@w3.org (参见 说明) 是讨论本规范的首选渠道。 发送电子邮件时, 请在主题中写入“credential-management”字样, 最好像这样: “[credential-management] …评论摘要…

将其作为工作草案发布并不意味着 W3C 及其成员对此的认可。本文件为草稿文档,可能随时被更新、替换或被其他文档废止。不应将本文件作为除进行中工作之外的正式引用。

本文件由 Web 应用安全工作组 制作。

本文件由在 W3C 专利政策 下运作的小组制作。 W3C 维护了一个与该小组交付物相关的任何专利披露的公开列表; 该页面也包含披露专利的说明。 个人如果确有专利知识并认为该专利包含实质性权利要求(Essential Claim(s)), 必须按照 W3C 专利政策第6节 的规定披露相关信息。

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

1. 简介

本节为非规范性内容。

登录网站比应有的要困难得多。用户代理处于一个独特的位置,能够在多方面改善这种体验,大多数现代用户代理已经通过在浏览器中原生提供某种程度的 credential management 来认识到这一点。例如,用户可以为网站保存用户名和密码;那些 凭证 随后会自动填充到登录表单中,尽管成功率各不相同。

属性 autocomplete 提供了一种声明性机制,网站可以通过它与用户代理协作——通过将特定字段标记为 "username" 或 "password"——以提高后者检测并填写登录表单的能力;用户代理还实现了各种检测启发式方法,以便与那些没有花时间在标记中提供这些细节的网站配合。

虽然这种启发式与声明式检测的组合运行得相对较好,但现状仍然存在一些检测困难的重大空白。具有不常见登录机制的网站(例如通过 XMLHttpRequest 提交凭证)很难可靠检测,用户希望使用联合身份提供者进行认证的情况也越来越常见。允许网站更直接地与用户代理的 凭证管理器 交互,一方面可以使 凭证管理器 更加准确,另一方面也能帮助用户进行联合登录。

这些用例在 § 1.1 Use CasesCredential Management: Use Cases and Requirements 中有更详细的探讨;本规范通过定义一个凭证管理器 API(Credential Manager API),尝试解决该文档概述的许多需求,网站可以使用该 API 为用户请求 凭证,并在用户成功登录时请求用户代理持久化这些凭证。

注意: 这里定义的 API 有意保持小而简单:它并不打算自身提供认证功能,而仅限于向现有用户代理实现的 凭证管理器 提供一个接口。该功能在 现在 就已很有价值,而不需要供应商或作者付出大量额外努力。当然,仍有许多可以做的事情。参见 § 9 Future Work,其中列出了一些我们暂时搁置、但可在未来 API 迭代中继续探讨的想法。

1.1. 使用场景

现代用户代理通常都为用户在登录网站时提供保存密码的能力,并且在用户再次访问网站时能全自动或半自动地填充这些密码。从网站的角度来看,这一行为完全不可见:网站不知道密码已被存储,也不会收到密码被填充的通知。这既有好处,也有不足。一方面,用户代理的密码管理器无论网站是否配合都能工作,这对用户来说非常好。另一方面,密码管理器的行为是一套脆弱且专有的启发式组合,旨在检测和填充登录表单、密码更改表单等。

现状中有几个突出问题值得关注:

2. 核心 API

从开发者的角度来看,凭证是一个对象,允许开发者为特定操作做出认证决策。本节定义了一个通用且可扩展的 Credential 接口,作为本规范及其他文档中定义的凭证的基类,并提供一组挂载在 navigator.credentials.* 上的 API,供开发者获取凭证。

不同的 凭证类型 都以接口的形式呈现给 JavaScript,这些接口直接或间接地继承Credential 接口。本规范定义了两个此类接口:PasswordCredentialFederatedCredential。其他规范,如 [WEBAUTHN],定义了其他凭证类型。

某个 凭证对于特定 源(origin) 是“有效”的,指的是该凭证可被该源接受用于认证。即使某一时刻的凭证有效,UA 也不能假定未来该凭证仍然有效,原因有以下几点:

  1. 如果账户持有人更改了密码,密码凭证可能会变为无效。

  2. 通过短信收到的令牌生成的凭证通常只在一次使用时有效。

一次性 凭证凭证源生成,凭证源可能是私钥、访问联合账户、或某个手机号接收短信的能力等。凭证源不会暴露给 Javascript,也不会在本规范中明确表示。为统一模型,我们把密码视为一种凭证源,通过复制生成密码凭证。

虽然 UA 不能假定一个有效凭证再次使用时仍然有效,也不能假定生成过有效凭证的凭证源未来能够再次生成有效凭证,但后者的可能性更大。通过记录(使用 store()) 过去哪些凭证是有效的,UA 能更好地在将来为用户提供有效的凭证源选择。

2.1. 基础设施

凭证管理器是一种应用程序、硬件设备或服务,用于存储、组织、管理并允许选择凭证。典型的凭证管理器包括数字钱包、密码管理器,以及passkey管理器。

用户代理必须在内部提供一个凭证存储,它是一种供应商特定的不透明存储机制,用于记录哪些凭证已被激活。它为凭证的访问和持久化提供以下功能:

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

  2. 检索凭证列表。此操作接受任意筛选条件,并返回与筛选条件匹配的一组凭证

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

此外,凭证存储应为维护一个prevent silent access 标志(除非另有说明,默认设为true)。如果该标志为true,则该源需要用户介入

Note: 关于用户介入的重要性,详见§ 5 用户介入

Note: 凭证存储是用户代理实现本文档所述 API 的内部实现细节,不会直接暴露给 Web。其他文档可能会为特定凭证类型规定更多能力。

本文档在其算法和正文中使用的一些基础概念依赖 Infra Standard [INFRA]

每个环境设置对象都有一个相关联的激活凭证类型,它是一个最初为空的集合

2.1.1. 基础设施算法

2.1.1.1. 与其祖先同源

环境设置对象 (settings) 满足以下算法返回 true 时, 称其为 与其祖先同源

  1. 如果 settings相关全局对象没有 关联的 Document,返回 false

  2. documentsettings相关全局对象关联的 Document

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

  4. originsettings

  5. navigabledocument节点可导航对象

  6. navigable 有非空 父级 时:

    1. navigablenavigable父级

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

  7. 返回 true

2.1.2. 凭证类型注册表

该注册表将凭证类型(即 [[type]] 的值)映射为与指定凭证类型相关的各种值。例如:选项成员标识符 (正式来说,是 字典成员标识符),用于 CredentialCreationOptionsCredentialRequestOptions (即“选项字典”)的规范。

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

凭证类型
(按字母顺序)
选项成员标识符 适用接口对象 获取权限策略 创建权限策略 规范 申请者联系方式
digital-credential digital DigitalCredential digital-credentials-get null [DIGITAL-CREDENTIALS] WICG
federated federated FederatedCredential null null 本规范:§ 4 联合凭证 W3C
identity identity IdentityCredential identity-credentials-get null [FEDCM] W3C
otp otp OTPCredential otp-credentials null [WEB-OTP] WICG
password password PasswordCredential null null 本规范:§ 3 密码凭证 W3C
public-key publicKey PublicKeyCredential publickey-credentials-get publickey-credentials-create [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 会 解析true,否则为 false

Credential 的默认 isConditionalMediationAvailable() 实现如下:

  1. 返回 false 解析的 Promise

任何支持 conditional 调解的 凭据类型 规范,必须显式重写该函数,使其 解析true

注意:如果此函数不存在, conditional 调解对于该 凭据类型 不受支持。

[[type]]

Credential接口对象 有一个名为 [[type]] 的内部槽, 其中存有一个 表示凭据类型的字符串。除非另有说明,否则该槽的值为空字符串。详见 § 2.1.2 凭据类型注册表 列表 凭据类型

注意: [[type]] 槽的值对于实现某一接口的所有凭据是相同的,这意味着开发者可以依赖 obj.type 返回一个明确表示其具体 Credential 类型的字符串。

[[discovery]]

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

和 Tobie/Dominic 讨论下接口对象相关内容,这里以及 § 2.5.1 请求凭据等处。我不确定术语是否准确。也许应该是 接口原型对象

某些 Credential 对象是绑定至源的:这些对象包含一个名为 [[origin]] 的内部槽,用于存储该 , 该 Credential 可能被 生效 的源。

2.2.1. Credential 内部方法

Credential 接口对象 拥有多个 内部方法, 用于凭据对象的获取与存储, 并在本节下方规定了默认的“无操作”实现。

除非另有规定,每个为 继承自 Credential 的接口创建的 接口对象 必须至少为这些内部方法之一提供实现,覆盖 Credential 的默认实现,具体应依据对应的 凭据类型。 例如,§ 3.2 PasswordCredential 接口§ 4.1 FederatedCredential 接口 以及 [WEBAUTHN]

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

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

  1. 返回空集合。

2.2.1.2. [[DiscoverFromExternalSource]] 内部方法
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)并行调用,参数为一个 origin、一个 CredentialRequestOptions 对象,以及一个布尔值,仅当调用方的 环境设置对象与其 祖先同源时为 true。 如果能够根据所提供的 options 返回一个 Credential ,则返回该对象;若没有凭据可用,则返回 null;如果发现失败(例如 options 参数错误会产生一个 TypeError),则抛出异常。 如果此类 Credential 仅对单次使用或仅在有限时间内 生效,该方法负责使用 凭据源生成新的 凭据

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

  1. 返回 null

2.2.1.3. [[Store]] 内部方法
[[Store]](credential, sameOriginWithAncestors)并行调用,参数为一个 Credential 和一个布尔值,仅当调用方的 环境设置对象与其 祖先同源时为 true。 当 Credential 被持久化到 凭据存储 后,该算法返回。

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

  1. 抛出 NotSupportedError

2.2.1.4. [[Create]] 内部方法
[[Create]](origin, options, sameOriginWithAncestors)并行调用,参数为一个 origin,一个 CredentialCreationOptions ,以及一个布尔值,仅当调用方的 环境设置对象 与其祖先同源时为 true。 该算法会:

当创建 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 仅暴露在 安全上下文(Secure Context) 中。

[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) 方法的参数。
参数 类型 可为 null 可选 说明
options CredentialRequestOptions 控制请求范围的属性集。
store(credential)

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

CredentialsContainer.store(credential) 方法的参数。
参数 类型 可为 null 可选 说明
credential Credential 要存储的凭据。
create(options)

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

CredentialsContainer.create(options) 方法的参数。
参数 类型 可为 null 可选 说明
options CredentialCreationOptions 用于创建 Credential 的参数。
preventSilentAccess()

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

注意: 这里的目的是让源能发出用户已退出登录的信号。即在用户点击“退出”按钮后,网站更新用户会话信息,并调用 navigator.credentials.preventSilentAccess()。这会设置 禁止静默访问标志(prevent silent access flag),意味着下次用户访问时不会自动将凭据返回给页面。

注意: 此方法之前名为 requireUserMediation(),现已废弃。

当创建一个 Navigator 对象(navigator)时,用户代理必须使用 navigator相关 Realm 创建一个 CredentialsContainer 对象,并将其与 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 请求凭据

uiMode 类型为 DOMString

该属性指定用户代理执行用户调解时,给定凭据请求的用户界面模式。各值含义详见 CredentialUiMode, 处理细节见 § 2.5.1 请求凭据

signal 类型为 AbortSignal

该属性允许开发者中止正在进行的 get() 操作。被中止的操作可能会正常完成(如在操作结束后才收到中止),也可能因 中止原因被拒绝。

本规范早期版本定义过一个布尔 unmediated 成员。将其设为 true 等价于将 mediation 设为 "silent", 设为 false 等价于将 mediation 设为 "optional"。

unmediated 应视为已废弃;新代码应只依赖 mediation

对于给定的 CredentialCreationOptionsCredentialRequestOptionsoptions), 相关凭据接口对象 是一组通过如下方式收集的 接口对象

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

  1. settings当前设置对象

  2. relevant interface objects 为一个 集合

  3. 对于 options 的每个 optionKeyoptionValue

    1. credentialInterfaceObject合适的接口对象 (在 settings全局对象上),其 Options Member IdentifieroptionKey

    2. 断言:credentialInterfaceObject[[type]] 槽等于 凭据类型 ,其 Options Member IdentifieroptionKey

    3. credentialInterfaceObject 添加到 relevant interface objects

  4. 返回 relevant interface objects

给定的 CredentialRequestOptionsoptions)如果以下步骤返回 true ,则 先验可匹配(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 而不会打扰用户。

注意: 典型用途是支持 “保持我登录”场景,即开发者希望在用户应自动签到时静默获取凭据,只有当用户主动选择登录时才提示登录界面。

optional

如果凭据可以在无需用户调解的情况下交付,则直接交付。如果 需要用户调解,用户代理会让用户决定。

注意: 这是 get() 的默认行为。适用于开发者确信用户正期望发起登录时(如用户刚刚点击“登录”按钮),此时用户看到 凭据选择器 也不会觉得奇怪或困惑。

conditional

对于 get(), 被发现的凭据会以非模态对话框展示给用户,并指明正在请求凭据的 。若用户在对话框外进行操作,则该对话框关闭,但 Promise 既不 resolve 也不 reject,页面不会因此收到错误。若用户在对话框中选取了凭据,则凭据返回给调用者。禁止静默访问标志 会被当作 true 处理,无论其实际值为何:conditional 行为总会涉及用户调解(若发现可用凭据)。

若未发现凭据,用户代理可根据凭据类型提示用户(如插入设备)。无论如何,get() 不得立即以 null 解决,以保护网站不知晓缺失凭据的事实。

只有当所有请求的 凭据接口都已重写 isConditionalMediationAvailable() 并返回以 true 解析的 Promise 时,网站才能将 conditional 作为参数传给 get()

对于 create(), 若用户先前已同意创建凭据且用户代理最近调解过认证,则 create() 调用可无需额外模态操作。否则(未调解或无同意),则必须抛出 "NotAllowedError" DOMException

required

不经过用户调解 用户代理绝不会交付凭据,即便该源未设置禁止静默访问标志

注意: 该要求用于如重新认证用户切换等场景。本要求仅影响当前操作,与此源的 禁止静默访问标志 无关。如需设置标志,开发者应调用 preventSilentAccess()

2.3.3. 界面模式

开发者通过 get(options) 发起请求时,可以通过选择合适的枚举值 CredentialUiMode 指定期望的 用户调解模式。

UI 模式字段无默认值。当未指定时, [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 方法必须仅根据 CredentialMediationRequirement 决定用户代理行为。

注意: 这让调用方可以区分不同的 用户调解形式。是否显示 UI 取决于 此请求的 CredentialMediationRequirement 值。 并非所有 CredentialUiModeCredentialMediationRequirement 组合都有意义,具体交互行为需参考相关类型的 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 方法规定。

enum CredentialUiMode {
  "immediate"
};
immediate

get() 的调用会使用户代理显示模态凭据选择对话框,或立即完成操作而不返回凭据。

这样可让网站向用户展示简化的登录 UI;否则可转而显示本地登录页,或继续未登录流程。

若无凭据可在凭据选择对话框中显示,则会跳过用户调解 (如不会提示用户输入凭据)。

注意: 本规范未提供类似 isConditionalMediationAvailable() 的静态方法来检测 immediate 是否可用。 若未来有更多凭据类型支持该调解模式,将需要一种更通用的特性检测机制,以表明某组合下哪些凭据类型受支持。

2.3.3.1. 示例
MegaCorp, Inc. 希望在条件允许时让用户无感登录。他们可以在加载落地页时为所有未登录用户调用 get() ,传入 mediation 字段值为 "silent"。 这样已选择“无需用户调解即登录”(见§ 5.2 要求用户调解)的用户会被直接登录, 其它用户则不会看到突兀的 凭据选择器
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. 也能通过将 get()mediation 字段设为 "required" 要求用户调解:

注意: 具体交互可能需用户进行认证(如输入主密码、指纹扫描等),具体取决于浏览器或凭据类型。

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. 希望支持多帐号同时登录。为让用户有机会选用不同凭据,可将 get()mediation 字段设为 "required", 可确保点击“添加账户”按钮时不会自动返回凭据:
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 扩展点,以及本文档的扩展接口: § 3.2 PasswordCredential 接口§ 4.1 FederatedCredential 接口

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

该属性允许开发者中止正在进行的 create() 操作。被中止的操作可能会正常完成(如在操作结束后才收到中止),也可能因 中止原因被拒绝。

2.5. 算法

2.5.1. 请求 Credential

请求 Credential 算法 接收一个 CredentialRequestOptionsoptions)参数,并返回一个 Promise :能唯一获取凭据时 resolve 为 Credential, 否则 resolve 为 null

  1. settings当前设置对象

  2. 断言:settings安全上下文

  3. documentsettings相关全局对象关联 Document

  4. 如果 document 不是 完全激活,则返回 一个 rejected 的 promise, 原因为 "InvalidStateError" DOMException

  5. 如果 options.signal中止, 返回 一个 rejected 的 promise, 原因为 options.signal中止原因

  6. interfacesoptions相关凭据接口对象

  7. 如果 interfaces空集合, 则返回 一个 rejected 的 promise, 原因为 "NotSupportedError" DOMException

  8. 遍历 interfaces 中每个 interface

    1. 如果 options.mediationconditionalinterface 不支持 conditional 用户调解, 返回 一个 rejected 的 promise, 原因为 "TypeError" DOMException

    2. 如果 options.uiModeimmediateinterface 不支持 immediate 用户调解, 返回 一个 rejected 的 promise, 原因为 "TypeError" DOMException

    3. 如果 settingsactive credential types 包含 interface[[type]], 返回 一个 rejected 的 promise, 原因为 "NotAllowedError" DOMException

    4. interface[[type]] 添加到 settingsactive credential types

  9. originsettingsorigin

  10. sameOriginWithAncestorstrue,如果 settings 与其 祖先同源,否则为 false

  11. 遍历 options相关凭据接口对象 interface

    1. permissioninterface[[type]] Get Permissions Policy

    2. 如果 permission 是 null,跳过。

    3. 如果 document 允许使用 permission,则返回 一个 rejected 的 promise,原因为 "NotAllowedError" DOMException

  12. p新建的 promise

  13. 并行上下文中执行以下步骤:

    1. credentials 为用 originoptionssameOriginWithAncestors 从凭据存储收集 Credential 的结果。

    2. 如果 credentials异常,则拒绝 p 并传递此异常。

    3. 若下列条件全部为真,则以 credentials[0] resolve p,并跳过后续步骤:

      1. credentials大小为 1

      2. origin要求用户调解

      3. options先验可匹配

      4. options.mediation 不为 "required"。

      5. options.mediation 不为 "conditional"。

      这也许不是最合适的模型。如果网站既支持用户名/密码又支持 webauthn,且前者用户不需要弹选择器而希望保持登录,该怎么处理?

    4. 如果 optionsmediation 为 "silent", resolve p 并传递 null,并跳过余下步骤。

    5. result提示用户选择 Credential,参数为 optionscredentials

    6. 如果 result接口对象

      1. originoptionssameOriginWithAncestors 执行 result[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors), 并用其结果替换 result

        如果该调用抛出 异常

        1. e 为此异常对象。

        2. 队列一个任务globalDOM 操作任务源, 执行下列子步骤:

          1. 拒绝 p,理由为 e

        3. 终止这些子步骤。

    7. 断言:resultnullCredential

    8. 如果 resultCredential, 用 result resolve p

    9. 如果 resultnulloptions.mediation 不为 conditional, 用 result resolve p

      注意:options.mediationconditional 且发现凭据为 null,promise p 不被 resolve。

  14. 在 promise settle 后

    1. 遍历 interfaces

      1. 移除 interface[[type]]settingsactive credential types

  15. 返回 p

2.5.2. 从凭证存储收集 Credential

给定 源(origin)origin)、CredentialRequestOptionsoptions)、以及一个布尔值,只有在调用上下文与祖先同源 时为 truesameOriginWithAncestors), 用户代理可以 从凭据存储收集 Credential ,返回本地存储并匹配 options 过滤条件的一组 Credential 对象。如果本地没有这样的 Credential ,返回集合为空:

  1. possible matches 为一个空集合。

  2. 遍历 options相关凭据接口对象 interface

    1. r 为执行 interface[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 内部方法后的结果,参数为 originoptionssameOriginWithAncestors。如抛出 异常,则重新抛出该异常。

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

    3. 遍历 r 中的每一项 c

      1. c 添加到 possible matches

  3. 返回 possible matches

2.5.3. 存储 Credential

存储 Credential 算法 接收一个 Credentialcredential),并返回一个 Promise ,一旦对象被持久化到 凭据存储后即 resolve。

  1. settings当前设置对象

  2. 断言:settings安全上下文

  3. 如果 settings相关全局对象关联 Document完全激活, 返回 rejected 的 promise, 原因为 "InvalidStateError" DOMException

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

  5. p新建 promise

  6. 如果 settings活跃凭据类型 包含 credential[[type]], 返回 rejected 的 promise, 原因为 "NotAllowedError" DOMException

  7. 添加 credential[[type]]settings活跃凭据类型 列表中。

  8. 并行环境中执行以下步骤:

    1. 运行 credential接口对象[[Store]](credential, sameOriginWithAncestors) 内部方法,传入 credentialsameOriginWithAncestors

      如抛出 异常

      1. e 为异常对象。

      2. 排队一个任务globalDOM 操作任务源,执行:

        1. 拒绝 p 并传递 e

      否则,resolve p 的值为 undefined

  9. React to p

    1. 移除 credential[[type]]settings活跃凭据类型

  10. 返回 p

2.5.4. 创建 Credential

创建 Credential 算法 接收一个 CredentialCreationOptionsoptions),并返回一个 Promise :如果所提供参数可创建 Credential, 则 resolve 为该对象;否则 resolve 为 null。在异常情况下, Promise 会 reject 合适的异常:

  1. settings当前设置对象

  2. 断言:settings安全上下文

  3. globalsettings全局对象

  4. document相关全局对象关联 Document

  5. 如果 document 不是 完全激活,返回 rejected 的 promise, 原因为 "InvalidStateError" DOMException

  6. sameOriginWithAncestorstrue,若 当前设置对象与其祖先同源,否则为 false

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

  8. 若下列任一条件成立,返回 rejected 的 promise, 原因为 NotSupportedError

    1. global 没有关联 Document

    2. interfacessize 大于 1。

      注意: 未来可能会放宽这个限制,让用户代理帮助用户选择多种凭据类型以支持“注册”场景。当前只允许字典有一个条目。

  9. 遍历 interfaces

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

    2. permission 为 null,跳过。

    3. document 允许使用 permission,返回 rejected 的 promise, 原因为 "NotAllowedError" DOMException

  10. 如果 options.signal中止, 返回 rejected 的 promise, 原因为 options.signal中止原因

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

  12. settings活跃凭据类型 包含 type, 返回 rejected 的 promise, 原因为 "NotAllowedError" DOMException

  13. type 添加到 settings活跃凭据类型

  14. originsettingsorigin

  15. p新建 promise

  16. 并行环境中执行以下步骤:

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

      如抛出 异常

      1. e 为异常对象。

      2. 排队一个任务globalDOM 操作任务源,然后执行下列子步骤:

        1. 拒绝 p,理由为 e

      3. 终止这些子步骤。

    2. 如果 rCredentialnull,则 resolve p 并传递 r,终止余下子步骤。

    3. 断言:r 是一个算法(如 § 2.2.1.4 [[Create]] 内部方法 中定义)。

    4. 排队一个任务globalDOM 操作任务源,执行下列子步骤:

      1. resolve p,并传递 promise 调用 r(参数为 global)的结果。

  17. React to p

    1. 移除 typesettings活跃凭据类型

  18. 返回 p

2.5.5. 防止静默访问

禁止静默访问算法 接收一个环境设置对象settings), 返回一个 Promise :一旦 prevent silent access 标志被持久化到 凭据存储 后即 resolve。

  1. originsettingsorigin

  2. 如果 settings相关全局对象关联 Document 不为 完全激活, 则返回 rejected 的 promise, 原因为 "InvalidStateError" DOMException

  3. p新建 promise

  4. 并行上下文执行以下步骤:

    1. 设置 origin禁止静默访问标志,在 凭据存储中。

    2. resolve 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) {
      // 用户要么没有该站点凭据,要么
      // 拒绝共享凭据。此处可回落至
      // 基础登录表单。
      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'  // 携带 Cookie
      };
      fetch('https://example.com/loginEndpoint', opt)
        .then(function (response) {
          if (/* |response| 指示登录成功 */) {
            // 记录该凭据已生效。见下方备注。
            navigator.credentials.store(credential);
            // 通知用户登录成功!执行所有需要登录的体验!
            // 或跳转到 /signed-in-experience 之类?
          } else {
            // 此处可回落至基础登录表单。
          }
        });
    }
  });

或者,网站也可以把凭据数据复制进一个 form 并调用 submit()

navigator.credentials
  .get({ 'password': true })
  .then(credential => {
    if (!credential) {
      return; // 同上……
    }
    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 跨域凭据访问), 或允许用户临时创建新凭据。开发者可通过每次凭据被成功使用后(即便刚通过 get() 获取后)都调用 store() ,优雅处理这种不确定性:如果凭据尚未存储到该源,用户会有机会确认保存;如果已存储,用户则不会被提示。

3.1.2. 登录后确认

为了确保用户在成功登录后能够保存新凭证,可以将凭证传递给 store()

如果用户通过 fetch() 将凭证提交到登录端点,可以根据响应判断是否登录成功,并通知用户代理。假设有如下登录表单:
<form action="https://example.com/login" method="POST" id="theForm">
  <label for="username">用户名</label>
  <input type="text" id="username" name="username" autocomplete="username">
  <label for="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();

      // 用触发 "submit" 事件的 PasswordCredential 构造一个新的 HTMLFormElement,
      // 会自动抓取带有 "username" 和 "current-password" autocomplete 属性的字段值:
      var c = new PasswordCredential(e.target);

      // fetch 表单的 action URL,并将新凭证对象作为 FormData 传递。如果响应表示登录成功,通知用户代理以便后续存储密码:
      var opt = {
        method: 'POST',
        body: new FormData(e.target),
        credentials: 'include'  // 发送 cookie。
      };
      fetch(e.target.action, opt).then(r => {
        if (/* |r| 是 "成功" Response */)
          navigator.credentials.store(c);
      });
    }
});

3.1.3. 修改密码

同样的存储机制可用于“修改密码”,无需任何修改:当用户更改凭证时,网站可通知用户代理用户已用新凭证成功登录。用户代理随后可以更新其存储的凭证:

MegaCorp 公司允许用户通过异步 POST 数据到后端服务器来修改密码。成功后,可通过调用 store() 并传入新信息来更新用户凭证。

假设有如下修改密码表单:

<form action="https://example.com/changePassword" method="POST" id="theForm">
  <input type="hidden" name="username" autocomplete="username" value="user">
  <label for="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();

    // 用触发 "submit" 事件的 PasswordCredential 构造一个新的 HTMLFormElement,
    // 会自动抓取带有 "username" 和 "new-password" autocomplete 属性的字段值:
    var c = new PasswordCredential(e.target);

    // fetch 表单的 action URL,并将新凭证对象作为 FormData 传递。如果响应表示成功,通知用户代理以便后续存储密码:
    var opt = {
      method: 'POST',
      body: new FormData(e.target),
      credentials: 'include'  // 发送 cookie。
    };
    fetch(e.target.action, opt).then(r => {
      if (/* |r| 是 "成功" 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]]

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

PasswordCredential(form)

该构造器接受一个 HTMLFormElementform),并执行如下步骤:

  1. origin当前设置对象

  2. r 为执行 通过 HTMLFormElement 创建 PasswordCredential,参数为 formorigin 的结果。

  3. 如果 r异常抛出 r

    否则返回 r

PasswordCredential(data)

该构造器接受一个 PasswordCredentialDatadata),并执行如下步骤:

  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)origin)、CredentialRequestOptionsoptions), 以及仅当调用上下文与祖先同源时为 true 的布尔值(sameOriginWithAncestors)。 该算法返回 凭据存储 中的 Credential 对象集合。如果没有可用的匹配 Credential 对象,则返回空集合。

如果 sameOriginWithAncestors 不是 true,该算法会抛出 NotAllowedError

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

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

    注意: 此限制用于解决 § 6.4 源混淆 中提出的问题。

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

  4. 返回检索 来自凭据存储且符合下列条件的凭据的结果:

    1. 凭据是 PasswordCredential

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

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

[[Create]](origin, options, sameOriginWithAncestors) 被调用时,参数为 originorigin), CredentialCreationOptionsoptions),以及仅当调用上下文与祖先同源时为 true 的布尔值 (sameOriginWithAncestors)。 算法若能创建 PasswordCredential 则返回之,否则返回 nullCredentialCreationOptions 字典必须有一个 password 成员,该成员为 HTMLFormElementPasswordCredentialData。 若该成员值无法用于创建 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 的布尔值(sameOriginWithAncestors)。算法在 credential 被持久化到 凭据存储 后返回 undefined

如果 sameOriginWithAncestors 不是 true,则算法会返回 NotAllowedError

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

    注意: 此限制旨在解决 § 6.4 源混淆 中提出的安全问题。

  2. 如果用户代理的 凭据存储 中已有 PasswordCredentialstored), 其 id 属性等于 credentialid,并且 [[origin]] 槽与 credential[[origin]] 同源,则:

    1. 若用户同意更新凭据(参见用户调解 定义),则:

      1. storedpassword 设为 credentialpassword

      2. storedname 设为 credentialname

      3. storediconURL 设为 credentialiconURL

    否则,如果用户同意存储凭据(参见用户调解 定义),则:

    1. 凭据存储 内存储一个 PasswordCredential ,其属性如下:

      id

      credentialid

      name

      credentialname

      iconURL

      credentialiconURL

      [[origin]]

      credential[[origin]]

      password

      credentialpassword

3.3.4. 通过 HTMLFormElement 创建 PasswordCredential

通过 HTMLFormElement 创建 PasswordCredential,传入一个 HTMLFormElementform)和一个 originorigin),运行如下步骤。

注意: § 3.1.2 登录后确认§ 3.1.3 修改密码 提供了推荐用法示例。

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

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

  3. formData 为执行 FormData 构造器,参数为 form 的结果。

  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 成员值为执行 formDataget() 方法,参数为 name 的结果,并将 newPasswordObserved 设为 true

          "current-password"

          如果 newPasswordObservedfalse, 设置 datapassword 成员值为执行 formDataget() 方法,参数为 name 的结果。

          注意:如果 newPasswordObservedfalse,则 new-password 字段优先于 current-password 字段。

          "photo"

          设置 dataiconURL 成员值为执行 formDataget() 方法,参数为 name 的结果。

          "name"
          "nickname"

          设置 dataname 成员值为执行 formDataget() 方法,参数为 name 的结果。

          "username"

          设置 dataid 成员值为执行 formDataget() 方法,参数为 name 的结果。

  7. c 为执行 通过 PasswordCredentialData 创建 PasswordCredential,参数为 data 的结果。如果抛出 异常,则重新抛出该异常。

  8. 断言:cPasswordCredential

  9. 返回 c

3.3.5. 通过 PasswordCredentialData 创建 PasswordCredential

利用 PasswordCredentialData 创建 PasswordCredential,给定一个 PasswordCredentialDatadata),按如下步骤操作。

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

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

    • dataid 成员的值

    • dataorigin 成员的值

    • datapassword 成员的值

  3. 设置 c 的属性如下:

    password

    datapassword 成员的值

    id

    dataid 成员的值

    iconURL

    dataiconURL 成员的值

    name

    dataname 成员的值

    [[origin]]

    dataorigin 成员的值。

  4. 返回 c

3.3.6. CredentialRequestOptionsPasswordCredential 的匹配

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

  1. 如果 options 有一个 password 成员且其值为 true,则返回 "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 标识 Provider

protocol 类型为 DOMString,只读,允许为 null

凭据的联合身份提供者协议(例如 "openidconnect")。如果该值为 null, 可根据 provider 推断协议。

[[type]]

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

[[discovery]]

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

FederatedCredential(data)

该构造函数接受 FederatedCredentialInitdata),并执行下列步骤:

  1. r 为执行 “从 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 Login 不应被称为 "Facebook"、"Facebook Login"、"FB"、"FBL"、"Facebook.com" 等等。应有一个规范标识符供所有人使用,因为一致的标识有助于用户代理提供帮助。

为保持一致,传递到本文档定义的 API(如 FederatedCredentialRequestOptionsproviders 数组或 FederatedCredentialprovider 属性)必须用该提供者用于登录的 origin 的 ASCII 序列化来标识。也就是说,Facebook 用 https://www.facebook.com,Google 用 https://accounts.google.com

这种 origin 的序列化不包括结尾的 U+002F 斜杠("/"),但用户代理应默默接受它:https://accounts.google.com/ 显然与 https://accounts.google.com 相同。

4.2. 算法

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

[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 被调用时,参数为 originorigin),CredentialRequestOptionsoptions), 以及仅当调用上下文与祖先同源 时为 true 的布尔值(sameOriginWithAncestors)。 该算法返回来自凭据存储的一组 Credential 对象。如果无匹配的 Credential ,则返回集合为空。

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

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

    注意: 此限制旨在解决 § 6.4 源混淆 中提出的问题。

  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) 被调用时,参数为 originorigin)、CredentialCreationOptionsoptions),以及一个仅当调用上下文与其祖先同源时为 true 的布尔值(sameOriginWithAncestors)。 该算法在可以创建时返回一个 FederatedCredential,否则返回 null,异常情况下抛出 异常

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

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

  3. 返回执行 通过 FederatedCredentialInit 创建 FederatedCredential, 参数为 options["federated"] 的结果。如果抛出 异常,则重新抛出该异常。

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

[[Store]](credential, sameOriginWithAncestors) 被调用时,传入一个 FederatedCredentialcredential),以及一个仅当调用上下文与其祖先同源时为 true 的布尔值 (sameOriginWithAncestors)。当 credential 持久化到 凭证存储后,该算法返回 undefined

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

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

    注意:此限制旨在解决 § 6.4 源混淆中提出的问题。

  2. 如果用户代理的 凭证存储中已包含一个 FederatedCredential, 其 id 属性等于 credentialid, 且其 [[origin]] 槽与 credential[[origin]]同源, 且其 provider 等于 credentialprovider, 则直接返回。

  3. 如果用户允许存储凭证(见 用户介入 的定义),则在 凭证存储中存储一个 FederatedCredential, 其属性如下:

    id

    credentialid

    name

    credentialname

    iconURL

    credentialiconURL

    [[origin]]

    credential[[origin]]

    provider

    credentialprovider

    protocol

    credentialprotocol

4.2.4. 通过 FederatedCredentialInit 创建 FederatedCredential

通过 FederatedCredentialInit 创建 FederatedCredential,给定一个 FederatedCredentialInitinit),运行如下步骤。

  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 暴露凭据信息可能会对用户隐私产生多种影响。因此,用户代理**必须**在多种场景下让用户参与,以确保用户明白发生了什么、他们的凭据将与谁共享。

我们称某个操作为用户调解,如果它是在获得用户明确同意后发生的。例如,同意可能通过用户在 凭据选择器界面上的直接交互来表达。通常,用户调解操作会涉及向用户展示某种界面,并请其做出决策。

未调解的(unmediated)操作则是在没有用户明确同意的情况下静默发生。例如,如果用户设置浏览器给予某个源持久的凭据访问权限,则可在不弹出决策界面的情况下提供凭据。

下面我们将阐述适用于所有凭据类型的一些通用要求,但请注意,用户代理具有较大自由度(它处于帮助用户的特权位置)。此外,特定凭据类型可能还有超出本文一般性要求的特殊规定。

5.1. 存储和更新凭证

凭据信息属于敏感数据,用户**必须**始终掌控这类信息的存储。无意间的凭据存储,例如,可能会让用户在某台设备上的本地资料与某个特定网络身份意外关联起来。为了降低此类意外风险:

  1. 未经用户调解,不应存储或更新凭据信息。 例如,用户代理可以在每次调用 store() 时,弹出“是否保存此凭据?”对话框。

    如果用户代理希望提供持久授权(如“始终保存密码”选项),可推断用户已同意(不过我们建议用户代理把范围尽量收窄——比如“始终保存_生成的_密码”或“始终保存本站密码”)。

  2. 用户代理在存储凭据时应该通知用户,例如通过在地址栏或类似位置显示图标等形式。

  3. 用户代理**必须**允许用户手动移除已存储的凭据。该功能可作为设置页面提供,或通过如上所述的通知界面实现。

5.2. 强制用户介入

默认情况下,所有用户调解所有源都是必需的,因为 防止静默访问标志凭据存储中被设置为 true。用户可以选择为某个源授予凭据的持续访问权 (例如“保持登录本站”选项),此时会将该标志设为 false。这样,用户总会自动登录该站点, 从易用性和便捷性角度来看很理想,但也可能带来意外影响(例如,有的用户代理会在多设备间同步这个标志状态)。

为了避免这种意外风险:

  1. 用户代理必须允许用户为某一源或所有源要求用户调解。该功能可作为全局开关实现,覆盖每个源的 防止静默访问标志,让其都返回 false, 也可以为指定源(或特定源的具体凭据)做更细粒度的设置。

  2. 用户代理不得在没有用户调解的情况下,将某个防止静默访问标志 设为 false。例如,凭据选择器 (见§ 5.3 凭据选择)可带有一个复选框,允许用户勾选后为该源在无调解时开放凭据, 或用户代理可在其凭据管理器引导流程中让用户设置默认选项。

  3. 用户代理在为某个源提供凭据时必须通知用户,比如可以在地址栏或类似位置显示图标。

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

5.3. 凭证选择

当对某个需要 用户调解的来源调用 get() 时,用户代理**必须**征求用户同意后方可共享凭据信息。 这通常应以凭据选择器的形式呈现:向用户展示可用于该站点的凭据列表, 让他们选择要提供给网站的凭据,或者完全取消此次请求。

选择器 的用户界面应以某种方式易于与网站自身产生的界面区分。例如,选择器可以以用户代理界面重叠且不可伪造的方式显示。

选择器 的界面**必须**包含请求凭据的来源信息。

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

用户代理可以为每个 Credential 对象内部关联额外信息(超出本文档规定属性), 以提升选择器的实用性。例如,可以通过 Favicons 区分不同身份提供方等。但所有这种附加信息**不得**直接暴露给 Web。

选择器 的交互细节未在此规定:鼓励用户代理探索不同 UI 设计,以帮助用户理解认证选项,并引导用户流程做出凭据选择。 不过选择器的接口如下:

用户代理可以让用户选择 Credential,参数包括 CredentialRequestOptions (options) 及从 凭据存储中发现的一组 Credential 对象(locally discovered credentials)。

此算法返回值可以是 null(用户拒绝与站点共享凭据时), 也可以是用户所选的 Credential 对象, 或者如果用户选择了某类型凭据,则为相关 Credential 接口对象

选择器界面可以将 locally discovered credentials 列表展示给用户,可能类似如下高度非规范的界面草图:

A mockup of what a chooser might look like.

如果 options先验可匹配, 选择器可能还应列出 options 中未在已有凭据列表里的相关凭据接口对象。例如,某站点支持 webauthn 风格认证器,则“安全密钥”可带图标列入选择器选项。

另请注意,在某些情况下用户代理可能会跳过显示选择器。 例如,如果唯一的相关凭据接口对象本身就需要用户操作, 用户代理可直接返回该接口,并依赖其内部调解流程完成用户授权。

6. 安全注意事项

以下各节为各种安全和隐私注意事项的指导原则。不同凭证类型可能会强制执行更严格或更宽松的版本。

6.1. 跨域凭证访问

凭据属于敏感信息,用户代理在判断何时可以安全地与网站共享时必须格外谨慎。最安全的做法是仅允许凭据分享到其被保存时的确切来源(origin)。然而,这对于 Web 来说往往过于严格:比如功能被分在 example.comadmin.example.com 等子域名中的网站。

为在减少用户困扰和保障凭据安全之间取得平衡,用户代理:

  1. 不得在方案(scheme)降级的情况下在来源间共享凭据。也就是说,将 http://example.com/ 上保存的凭据提供给 https://example.com/ 是合理的(以鼓励开发者迁移到安全传输),但反过来则危险。

  2. 可以利用公共后缀列表 [PSL] 通过比较凭据的 可注册域get() 被调用的来源做比较,确定凭据的有效作用域。即:当从 https://www.example.com/ 调用 get() 时,可以将 https://admin.example.com/https://example.com/ 上保存的凭据提供给用户,反之亦然。

  3. 当凭据的来源不是调用来源的精确匹配时,不得在没有用户调解的情况下, 响应 get() 向该来源提供凭据。即,Credential 对象在 https://www.example.com 上不会直接返回 https://example.com 的凭据,但可通过选择器界面供用户选择。

6.2. 凭证泄露

开发者应当采取一些预防措施,通过设置合理的内容安全策略(Content Security Policy,[CSP]),限制数据可以发送到的端点,从而降低跨站脚本攻击演变为对用户账户的持久访问的风险。特别是,开发者应确保在页面策略中显式或隐式地设置以下指令:

当然,开发者还应正确转义输入输出,并考虑使用其他防护措施,比如 Subresource Integrity [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 显示站点 favicon),那么对这些图片的请求**不得**直接与选择器的实例化关联,以避免泄露选择器的使用情况。一种做法是在保存或更新 Credential 时后台获取图片, 并在Credential生命周期内缓存。

这些图片**必须**使用如下 fetch 设置获取:credentials mode 设为 "omit", service-workers mode 设为 "none", client 设为 nullinitiator 设为空字符串, destination 设为 "subresource"。

此外,如果用户代理允许用户更改凭据关联的名称或图标,则这种数据变动**不应**暴露给网站 (考虑某用户给同一来源的两个凭据命名为“我的小号”和“我的主号”等情况)。

7.3. 本地存储数据

该 API 允许某个 将数据与用户的个人资料持久存储。由于大多数用户代理对凭证数据和“浏览数据”(如 cookie 等)处理方式不同,这可能导致用户在清除 cookie 时以为所有来源痕迹都被清除,实际仍有凭证数据保留而感到意外。

用户代理应提供 UI,清楚地向用户展示某个源已存储凭证数据,并应让用户易于移除这些数据。

8. 实现注意事项

本节为非规范内容。

8.1. 网站作者

此处应补充关于何时及如何使用该 API 的一些思考,尤其是关于 mediation 的相关内容。 [w3c/webappsec Issue #290]

说明通过 fetch() 携带 FormData body 提交凭据时的编码限制。

为某一凭据类型做特性检测时,建议开发者验证相关 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 使用 AbortController 和 AbortSignal 对象于 API

    ExampleCredential 的 internal 方法 [[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 被调用时,传入 originorigin)、CredentialRequestOptions 对象(options)和布尔值(仅当调用上下文与祖先同源时为 true)。 算法返回符合 options 的 Credential 对象集合。如无匹配 Credential ,返回空集合。
    1. 断言:options[example] 存在。

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

    3. 遍历凭据存储中每个 credential

      1. ...

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

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

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

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

    dictionary ExampleCredentialInit {
      // Definition goes here.
    };
    
    partial dictionary CredentialCreationOptions {
      ExampleCredentialInit example;
    };
    
  7. 如果新凭据类型支持 conditional 用户调解, 则定义 ExampleCredential/isConditionalMediationAvailable() 返回 resolved 的 promise,值为 true

  8. § 2.1.2.1 注册项要求与更新流程中的流程, 为新 "example" 凭据类型 及其对应项加入凭据类型注册表

    注意:凭据类型的 options 字典的 选项成员标识符, 在 CredentialCreationOptionsCredentialRequestOptions 中需一致,且应与 Credential 接口对象[[type]] 值相同。

你可能还会发现有必要增加新原语。例如在某些复杂的多因子登录流程中需要一次性返回多个 Credential 对象。可以以通用方式为 CredentialsContainer 增设 getAll() 方法,返回一个 sequence<Credential>,并定义合理的机制来支持请求不同类型的凭据。

如有此类扩展,建议联系 public-webappsec@ 咨询和评审。

8.3. 浏览器扩展

理想情况下,支持扩展系统的用户代理会允许第三方钩入这些 API 端点,以改善第三方凭证管理软件的行为,就像用户代理通过命令式方式改善自身一样。

这既可以是用户代理中介的复杂新 API,也可以仅允许扩展覆盖 get()store() 端点以满足自身需求。

9. 未来工作

本节为非规范内容。

此处定义的 API 仅以极简方式将用户代理的凭证管理器暴露给 Web,并允许 Web 协助这些凭证管理器识别何时正在使用联合身份提供者。下一步的合理方向,将会类似于[WEB-LOGIN]等文档中描绘的内容(以及在某种程度上,Mozilla 的 BrowserID [BROWSERID])。

用户代理处于一个独特位置,可以有效调解用户、身份提供者和网站之间的关系。如果用户代理能减少典型认证流程中的风险和困惑,用户的处境将比现在大为改善。

一种自然的信息暴露方式可能是扩展 FederatedCredential 接口,增加如认证令牌等属性,或添加某种声明提供者支持认证类型的 manifest 格式属性。

此处描述的 API 设计为足够可扩展,以支持需要用户交互的用例,甚至可能涉及除了请求凭证的网站之外的其他网站。我们希望我们采用的基于 Promise 的系统,足够扩展以支持此类异步流程,这些流程可能需要多个浏览上下文之间的某种交互(例如 idp.com 上的调解活动可解析传回给 rp.com 的 Promise),或者未来支持设备与用户代理之间的交互(例如 [WEBAUTHN]),而无需从零重新设计 API。

循序渐进。

索引

本规范定义的术语

引用文献定义的术语

参考文献

规范性引用

[CSP]
Mike West;Antonio Sartori。内容安全策略第3级(Content Security Policy Level 3)。2026年2月11日。工作草案(WD)。URL:https://www.w3.org/TR/CSP3/
[DIGITAL-CREDENTIALS]
Marcos Cáceres;Sam Goto。数字凭据(Digital Credentials)。URL:https://wicg.github.io/digital-credentials/
[DOM]
Anne van Kesteren。DOM 标准(DOM Standard)。现行标准(Living Standard)。URL:https://dom.spec.whatwg.org/
[FEDCM]
Nicolas Pena Moreno。联合凭据管理 API(Federated Credential Management API)。2024年8月20日。首份公开工作草案(FPWD)。URL:https://www.w3.org/TR/fedcm-1/
[FETCH]
Anne van Kesteren。Fetch 标准(Fetch Standard)。现行标准。URL:https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren 等。HTML 标准(HTML Standard)。 现行标准。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren;Domenic Denicola。基础结构标准(Infra Standard)。现行标准。URL:https://infra.spec.whatwg.org/
[PERMISSIONS]
Marcos Caceres;Mike Taylor。权限(Permissions)。2025年10月6日。工作草案(WD)。URL:https://www.w3.org/TR/permissions/
[PROMISES-GUIDE]
Domenic Denicola。编写基于 Promise 的规范(Writing Promise-Using Specifications)。2018年11月9日。TAG 发现文档。URL:https://www.w3.org/2001/tag/doc/promises-guide
[PSL]
公共后缀列表(Public Suffix List)。URL:https://publicsuffix.org/
[SECURE-CONTEXTS]
Mike West。安全上下文(Secure Contexts)。2023年11月10日。候选推荐稿(CRD)。URL:https://www.w3.org/TR/secure-contexts/
[WEB-OTP]
WebOTP API。社区组草案报告。URL:https://wicg.github.io/web-otp/
[WEBAUTHN-3]
Michael Jones 等。Web 认证:用于访问公钥凭据的 API - 第3级(Web Authentication: An API for accessing Public Key Credentials - Level 3)。2026年1月13日。候选推荐稿(CR)。URL:https://www.w3.org/TR/webauthn-3/
[WEBIDL]
Edgar Chen;Timothy Gu。Web IDL 标准(Web IDL Standard)。现行标准。URL:https://webidl.spec.whatwg.org/
[XHR]
Anne van Kesteren。XMLHttpRequest 标准(XMLHttpRequest Standard)。现行标准。URL:https://xhr.spec.whatwg.org/

资料性引用

[BROWSERID]
Ben Adida; 等. BrowserID. 2013年2月26日. URL: https://github.com/mozilla/id-specs/blob/prod/browserid/index.md
[SRI]
Devdatta Akhawe; 等. 子资源完整性(Subresource Integrity). 2016年6月23日. REC. URL: https://www.w3.org/TR/SRI/
[WEB-LOGIN]
Jason Denizac; Robin Berjon; Anne van Kesteren. web-login. URL: https://github.com/jden/web-login
[WEBAUTHN]
Dirk Balfanz; 等. Web Authentication:用于访问公钥凭证的API第1级(An API for accessing Public Key Credentials Level 1). 2019年3月4日. REC. URL: https://www.w3.org/TR/webauthn-1/
[XMLHTTPREQUEST]
Anne van Kesteren; 等. XMLHttpRequest 第1级(XMLHttpRequest Level 1). 2016年10月6日. NOTE. URL: https://www.w3.org/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 作为 body 提交凭证时的编码限制。
MDN

Credential/id

In all current engines.

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

Credential/type

In all current engines.

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

Credential

In all current engines.

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

CredentialsContainer/create

In all current engines.

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

CredentialsContainer/get

In all current engines.

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

CredentialsContainer/preventSilentAccess

In all current engines.

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

CredentialsContainer/store

In all current engines.

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

CredentialsContainer

In all current engines.

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

FederatedCredential/FederatedCredential

In only one current engine.

FirefoxNoneSafariNoneChrome51+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

FederatedCredential/protocol

In only one current engine.

FirefoxNoneSafariNoneChrome51+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

FederatedCredential/provider

In only one current engine.

FirefoxNoneSafariNoneChrome51+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

FederatedCredential

In only one current engine.

FirefoxNoneSafariNoneChrome51+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Navigator/credentials

In all current engines.

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

PasswordCredential/PasswordCredential

In only one current engine.

FirefoxNoneSafariNoneChrome51+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

PasswordCredential/iconURL

In only one current engine.

FirefoxNoneSafariNoneChrome51+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

PasswordCredential/name

In only one current engine.

FirefoxNoneSafariNoneChrome51+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

PasswordCredential/password

In only one current engine.

FirefoxNoneSafariNoneChrome60+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

PasswordCredential

In only one current engine.

FirefoxNoneSafariNoneChrome51+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?