W3C

Web身份验证:
访问公钥凭证的API
第二级

W3C推荐标准,

此版本:
https://www.w3.org/TR/2021/REC-webauthn-2-20210408/
最新发布版本:
https://www.w3.org/TR/webauthn-2/
编辑草案:
https://w3c.github.io/webauthn/
以前的版本:
实施报告:
https://www.w3.org/2020/12/webauthn-report.html
问题跟踪:
GitHub
编辑:
(谷歌)
(Mozilla)
(微软)
(微软)
(Yubico)
前任编辑:
(谷歌)
(微软)
(谷歌)
(谷歌)
(贝宝)
(微软)
(Nok Nok实验室)
贡献者:
John Bradley (Yubico)
Christiaan Brand (谷歌)
Adam Langley (谷歌)
Giridhar Mandyam (高通)
Nina Satragno (谷歌)
Nick Steele (Gemini)
Jiewen Tan (苹果)
Shane Weeden (IBM)
Mike West (谷歌)
Jeffrey Yasskin (谷歌)
测试:
web-platform-tests webauthn/ (持续工作)

请查看勘误表,以获取自发布以来报告的任何错误或问题。


摘要

本规范定义了一个API,允许Web应用程序创建和使用基于公钥的、强大的、可证明的范围限定的凭证,用于强用户身份验证。从概念上讲,一个或多个公钥凭证,每一个都范围限定到给定的WebAuthn依赖方,由Web应用程序请求并绑定认证器。用户代理介导对认证器及其公钥凭证的访问,以保护用户隐私。认证器负责确保没有在未经用户同意的情况下执行的操作。认证器通过证明依赖方提供其属性的密码学证明。本规范还描述了符合WebAuthn标准的认证器的功能模型,包括其签名和证明功能。

本文档状态

本节描述了本文档在出版时的状态。其他文档可能会取代本文档。当前 W3C出版物和本技术报告的最新修订版列表可在 W3C技术报告索引找到:https://www.w3.org/TR/。

本文档由Web身份验证工作组发布为推荐标准。

欢迎对本规范提供反馈和意见。请使用Github问题。 讨论也可以在public-webauthn@w3.org archives中找到。

W3C推荐标准是一项规范,在经过广泛的共识构建后,得到了W3C及其成员的认可。W3C建议将此规范广泛部署为Web的标准。

本文档已由W3C成员、软件开发人员及其他W3C小组和感兴趣的各方进行审查,并已获得主管的认可为W3C推荐标准。这是一个稳定的文档,可用作参考材料或被其他文档引用。W3C在制定推荐标准中的角色是引起对该规范的注意,并促进其广泛部署。这增强了Web的功能性和互操作性。

本文档由一个根据2017年8月1日 W3C 专利政策运作的小组制作。W3C维护一个公开的专利披露列表,其中列出了与该小组的成果相关的任何专利披露;该页面还包括披露专利的说明。个人如果实际知道某项专利,并且认为该专利包含必要的声明,则必须根据 W3C 专利政策第6节披露相关信息。

本文档受2020年9月15日 W3C 流程文档的管理。

1. 介绍

本节不是规范性条款。

本规范定义了一种API,允许创建和使用强大、可证明的、范围、基于公钥的凭证,由Web应用程序用于强身份验证用户。公钥凭证WebAuthn身份验证器根据WebAuthn依赖方的要求创建并存储,需经用户同意。随后,公钥凭证只能由属于该依赖方访问。这一范围由符合标准的用户代理身份验证器共同强制执行。此外,跨依赖方的隐私得到维护;依赖方无法检测到任何属性,甚至无法得知其他范围内的凭证的存在,这些凭证被依赖方所限制。

依赖方在与用户相关的两个不同但相关的程序中使用Web身份验证API。第一个是注册,在该过程中在身份验证器上创建公钥凭证,并与当前用户的账户依赖方进行范围绑定(账户可能已经存在,或可能在此时创建)。第二个是身份验证,在该过程中,依赖方会接收到一个身份验证声明,以证明注册了公钥凭证的用户的存在和同意。从功能上讲,Web身份验证API包括一个PublicKeyCredential ,它扩展了凭证管理API[CREDENTIAL-MANAGEMENT-1],以及允许这些凭证与navigator.credentials.create()navigator.credentials.get()一起使用的基础设施。前者在注册期间使用,而后者在身份验证期间使用。

总体而言,符合标准的身份验证器保护公钥凭证,并与用户代理交互以实现Web身份验证API。符合标准的身份验证器可以在执行的软件中实现,(a) 在通用计算设备上,(b) 在设备上的安全执行环境、受信任的平台模块(TPM)或安全元件(SE)上,或 (c) 离线实现。实现于设备上的身份验证器称为平台身份验证器。实现于离线设备的身份验证器(漫游身份验证器)可以通过诸如通用串行总线(USB)、蓝牙低能耗(BLE)或近场通信(NFC)等传输方式进行访问。

1.1. 规范路线图

虽然许多 W3C 规范主要面向用户代理开发者和网络应用开发者(即“网络作者”),但 Web 身份验证的性质要求多种受众正确使用此规范,如下所述。

所有受众 应首先阅读 § 1.2 用例§ 1.3 示例 API 使用场景§ 4 术语,并应参考 [WebAuthnAPIGuide] 以获取整体教程。 除此之外,本文档的目标受众主要有以下几组:

注:除了 Web认证API 本身,本规范还定义了一个请求-响应的 加密协议——WebAuthn/FIDO2 协议——在 WebAuthn 依赖方服务器和 认证器之间,其中 依赖方 的请求包含一个 挑战 和其他由 依赖方 提供并发送给 认证器 的输入数据。 请求通过 HTTPS、依赖方 Web应用程序WebAuthn API 和用户代理与 认证器 之间的 平台特定通信通道传递。 认证器 会回复一个经过数字签名的 认证器数据 消息和其他输出数据,这些数据通过相同的路径反向传送回 依赖方服务器。 协议的细节根据是 认证 操作 还是 注册 操作由 依赖方 发起而有所不同。 参见 图1图2

对于Web认证部署的端到端安全性至关重要的是,每个组件的角色——依赖方 服务器、客户端,以及 认证器—— 以及 § 13 安全考虑§ 14 隐私考虑,应当被所有听众充分理解 并为所有听众所知晓

1.2. 用例

以下用例场景展示了两种非常不同类型的身份验证器的使用,同时概述了更多的场景。其他场景,包括示例代码,将在§ 1.3 示例 API 使用场景中给出。

1.2.1. 注册

1.2.2. 身份验证

1.2.3. 新设备注册

此用例场景展示了一个依赖方如何利用组合的漫游身份验证器(例如 USB 安全密钥)和平台身份验证器(例如内置指纹传感器),使得用户可以:

注意:注册多个身份验证器用于一个账户的这种方法在账户恢复用例中也很有用。

1.2.4. 其他用例和配置

还可以实现多种其他用例和配置,包括(但不限于):

1.3. 示例 API 使用场景

本节不是规范性内容。

在本节中,我们将通过一些公钥凭证的生命周期事件,并提供相应的示例代码来使用该 API。请注意,这只是一个示例流程,并不限制 API 的使用范围。

与前面的部分一样,此流程关注于涉及第一因素漫游身份验证器的用例,该身份验证器具有自己的显示屏。例如,这种身份验证器的一个例子是智能手机。其他身份验证器类型也由此 API 支持,具体取决于客户端平台的实现。例如,此流程在没有修改的情况下也适用于嵌入在客户端设备中的身份验证器的情况。该流程也适用于没有自己显示屏的身份验证器(类似于智能卡),但需考虑特定的实现。具体而言,客户端平台需要显示任何原本由身份验证器显示的提示,且身份验证器需要允许客户端平台枚举所有身份验证器的凭证,以便客户端能够提供适当的提示信息。

1.3.1. 注册

这是首次流程,其中创建并在服务器上注册一个新凭证。在此流程中,WebAuthn 依赖方平台身份验证器漫游身份验证器没有偏好。

  1. 用户访问 example.com,该网站提供一个脚本。此时,用户可能已经使用传统的用户名和密码、其他身份验证器或其他可被依赖方接受的方法登录。或者,用户可能正在创建新账户。

  2. 依赖方 脚本运行下面的代码片段。

  3. 客户端平台 搜索并找到身份验证器。

  4. 客户端连接到身份验证器,如果需要,执行任何配对操作。

  5. 身份验证器向用户显示适当的 UI,以便用户提供生物识别或其他授权手势

  6. 身份验证器向客户端返回响应,随后客户端将响应返回给依赖方脚本。如果用户拒绝选择身份验证器或提供授权,将返回适当的错误。

  7. 如果创建了新凭证,

    • 依赖方脚本将新生成的凭证公钥发送到服务器,以及其他信息,例如关于身份验证器来源和特性的证明。

    • 服务器在其数据库中存储凭证公钥,并将其与用户及其特性关联,并存储一个友好的名称以备后用。

    • 脚本可以在本地存储中存储诸如凭证 ID的数据,以改善未来的用户体验,缩小用户的凭证选择范围。

生成并注册新密钥的示例代码如下:

if (!window.PublicKeyCredential) { /* Client not capable. Handle error. */ }

var publicKey = {
  // The challenge is produced by the server; see the Security Considerations
  challenge: new Uint8Array([21,31,105 /* 29 more random bytes generated by the server */]),

  // Relying Party:
  rp: {
    name: "ACME Corporation"
  },

  // User:
  user: {
    id: Uint8Array.from(window.atob("MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII="), c=>c.charCodeAt(0)),
    name: "alex.mueller@example.com",
    displayName: "Alex Müller",
  },

  // This Relying Party will accept either an ES256 or RS256 credential, but
  // prefers an ES256 credential.
  pubKeyCredParams: [
    {
      type: "public-key",
      alg: -7 // "ES256" as registered in the IANA COSE Algorithms registry
    },
    {
      type: "public-key",
      alg: -257 // Value registered by this specification for "RS256"
    }
  ],

  authenticatorSelection: {
    // Try to use UV if possible. This is also the default.
    userVerification: "preferred"
  },

  timeout: 360000,  // 6 minutes
  excludeCredentials: [
    // Don’t re-register any authenticator that has one of these credentials
    {"id": Uint8Array.from(window.atob("ufJWp8YGlibm1Kd9XQBWN1WAw2jy5In2Xhon9HAqcXE="), c=>c.charCodeAt(0)), "type": "public-key"},
    {"id": Uint8Array.from(window.atob("E/e1dhZc++mIsz4f9hb6NifAzJpF1V4mEtRlIPBiWdY="), c=>c.charCodeAt(0)), "type": "public-key"}
  ],

  // Make excludeCredentials check backwards compatible with credentials registered with U2F
  extensions: {"appidExclude": "https://acme.example.com"}
};

// Note: The following call will cause the authenticator to display UI.
navigator.credentials.create({ publicKey })
  .then(function (newCredentialInfo) {
    // Send new credential info to server for verification and registration.
  }).catch(function (err) {
    // No acceptable authenticator or user refused consent. Handle appropriately.
  });

1.3.2. 使用用户验证平台认证器进行注册

这是当WebAuthn 依赖方特别希望创建公钥凭证时的示例流程, 使用用户验证平台认证器

  1. 用户访问example.com并点击登录按钮,系统将用户重定向到login.example.com。

  2. 用户输入用户名和密码进行登录。登录成功后,用户被重定向回example.com。

  3. 依赖方脚本运行下面的代码片段。

    1. 用户代理检查是否有可用的用户验证平台认证器。如果没有,则终止此流程。

    2. 依赖方询问用户是否希望使用它创建凭证。如果用户拒绝,则终止此流程。

    3. 用户代理和/或操作系统显示适当的UI,并引导用户使用其中一个可用的平台认证器创建凭证。

    4. 凭证成功创建后,依赖方脚本将新凭证传送到服务器。

if (!window.PublicKeyCredential) { /* Client not capable of the API. Handle error. */ }

PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
    .then(function (uvpaAvailable) {
        // If there is a user-verifying platform authenticator
        if (uvpaAvailable) {
            // Render some RP-specific UI and get a Promise for a Boolean value
            return askIfUserWantsToCreateCredential();
        }
    }).then(function (userSaidYes) {
        // If there is a user-verifying platform authenticator
        // AND the user wants to create a credential
        if (userSaidYes) {
            var publicKeyOptions = { /* Public key credential creation options. */};
            return navigator.credentials.create({ "publicKey": publicKeyOptions });
        }
    }).then(function (newCredentialInfo) {
        if (newCredentialInfo) {
            // Send new credential info to server for verification and registration.
        }
    }).catch(function (err) {
        // Something went wrong. Handle appropriately.
    });

1.3.3. 身份验证

这是用户在已经注册凭证的情况下访问网站并希望使用该凭证进行身份验证的流程。

  1. 用户访问example.com,网站加载一个脚本。

  2. 该脚本向客户端请求身份验证断言,提供尽可能多的信息以缩小用户可接受凭证的选择范围。这些信息可以来自注册后本地存储的数据,或通过其他方式,例如提示用户输入用户名。

  3. 依赖方脚本运行以下代码片段之一。

  4. 客户端平台搜索并找到认证器。

  5. 客户端连接到认证器,并在必要时执行配对操作。

  6. 认证器向用户显示通知,表示需要用户的注意。打开通知后,用户会看到一个友好的可接受凭证的选择菜单,该菜单使用创建凭证时提供的账户信息,以及有关请求这些密钥的的一些信息。

  7. 认证器从用户那里获取生物识别或其他授权手势

  8. 认证器向客户端返回响应,而客户端又将响应返回给依赖方脚本。如果用户拒绝选择凭证或提供授权,则返回适当的错误。

  9. 如果成功生成并返回了断言,

    • 脚本将断言发送到服务器。

    • 服务器检查断言,提取凭证 ID,在其数据库中查找注册的凭证公钥,并验证断言签名。如果有效,它会查找与断言的凭证 ID相关联的身份,该身份现在已通过身份验证。如果服务器不识别凭证 ID(例如,因不活跃而被注销),则身份验证失败;每个依赖方将以其自己的方式处理此情况。

    • 服务器现在执行成功身份验证后通常会执行的操作——返回成功页面,设置身份验证cookies等。

如果依赖方脚本没有任何可用的提示(例如,来自本地存储的数据)来帮助缩小凭证列表,则执行此类身份验证的示例代码可能如下所示:

if (!window.PublicKeyCredential) { /* Client not capable. Handle error. */ }

// credentialId is generated by the authenticator and is an opaque random byte array
var credentialId = new Uint8Array([183, 148, 245 /* more random bytes previously generated by the authenticator */]);
var options = {
  // The challenge is produced by the server; see the Security Considerations
  challenge: new Uint8Array([4,101,15 /* 29 more random bytes generated by the server */]),
  timeout: 120000,  // 2 minutes
  allowCredentials: [{ type: "public-key", id: credentialId }]
};

navigator.credentials.get({ "publicKey": options })
    .then(function (assertion) {
    // Send assertion to server for verification
}).catch(function (err) {
    // No acceptable credential or user refused consent. Handle appropriately.
});

另一方面,如果依赖方脚本有一些提示可以帮助它缩小凭证列表,那么执行这种认证的示例代码可能如下所示。请注意,此示例还演示了如何使用凭证属性扩展

if (!window.PublicKeyCredential) { /* Client not capable. Handle error. */ }

var encoder = new TextEncoder();
var acceptableCredential1 = {
    type: "public-key",
    id: encoder.encode("BA44712732CE")
};
var acceptableCredential2 = {
    type: "public-key",
    id: encoder.encode("BG35122345NF")
};

var options = {
  // The challenge is produced by the server; see the Security Considerations
  challenge: new Uint8Array([8,18,33 /* 29 more random bytes generated by the server */]),
  timeout: 120000,  // 2 minutes
  allowCredentials: [acceptableCredential1, acceptableCredential2],
  extensions: { 'credProps': true }
};

navigator.credentials.get({ "publicKey": options })
    .then(function (assertion) {
    // Send assertion to server for verification
}).catch(function (err) {
    // No acceptable credential or user refused consent. Handle appropriately.
});

1.3.4. 中止认证操作

下面的示例展示了开发者如何使用AbortSignal参数中止凭证注册操作。类似的过程也适用于认证操作。

const authAbortController = new AbortController();
const authAbortSignal = authAbortController.signal;

authAbortSignal.onabort = function () {
    // Once the page knows the abort started, inform user it is attempting to abort.
}

var options = {
    // A list of options.
}

navigator.credentials.create({
    publicKey: options,
    signal: authAbortSignal})
    .then(function (attestation) {
        // Register the user.
    }).catch(function (error) {
        if (error == "AbortError") {
            // Inform user the credential hasn’t been created.
            // Let the server know a key hasn’t been created.
        }
    });

// Assume widget shows up whenever authentication occurs.
if (widget == "disappear") {
    authAbortController.abort();
}

1.3.5. 注销

以下是可能需要注销凭证的情况。请注意,所有这些情况都在服务器端处理,并不需要此处指定的API的支持。

1.4. 平台特定实施指南

本规范定义了在一般情况下如何使用Web身份验证。当在特定平台支持(例如应用程序)下使用Web身份验证时,建议查看平台特定的文档和指南,以获取额外的指导和限制。

2. 符合性

本规范定义了三个符合性类别。每个类别的成员必须能够抵御其他类别中不符合标准或恶意成员的攻击。

2.1. 用户代理

用户代理必须按照§ 5 Web 身份验证 API中的描述行为,才能被认为是符合标准的。符合标准的用户代理可以以任何所需的方式实现本规范中给出的算法,只要最终结果与规范算法的结果无异。

符合标准的用户代理还必须是本规范的IDL片段的符合实现,如“Web IDL”规范中所述。[WebIDL]

2.1.1. 作为 DOMString 类型的枚举

枚举类型未被Web IDL的其他部分引用,因为这会阻止其他值的使用,而不更新本规范及其实现。为了向后兼容,客户端平台依赖方应处理未知值。此规范中的枚举存在于此,仅用于文档和注册。在其他地方表示枚举时,它们被类型化为DOMString,例如在transports中。

2.2. 认证器

一个WebAuthn 认证器必须提供§ 6 WebAuthn 认证器模型中定义的操作,并且这些操作必须按照描述的方式行为。这是认证器可供符合标准的用户代理使用的一组功能和安全要求。

§ 1.2 用例中所述,认证器可以在用户代理下的操作系统中实现,或者在外部硬件中,或两者的结合。

2.2.1. 与 FIDO U2F 的向后兼容性

认证器仅支持§ 8.6 FIDO U2F 声明格式的情况下,没有机制来存储用户句柄,因此返回的userHandle将始终为 null。

2.3. WebAuthn 依赖方

一个WebAuthn 依赖方必须按照§ 7 WebAuthn 依赖方操作中的描述行为,以获得本规范提供的所有安全利益。有关此的进一步讨论,请参见§ 13.4.1 WebAuthn 依赖方的安全利益

2.4. 所有符合性类别

上述一致性类的成员执行的所有CBOR编码必须使用CTAP2规范的CBOR编码形式进行编码。上述一致性类的所有解码器应拒绝未在CTAP2规范的CBOR编码形式中有效编码的CBOR,并且应拒绝包含重复映射键的消息。

3. 依赖关系

本规范依赖于几个其他基础规范,列在下面以及通过引用定义的术语中。

Base64url 编码

术语Base64url 编码指的是使用在[RFC4648]第5节中定义的URL和文件名安全字符集进行的base64编码,省略所有尾随的'='字符(如第3.2节允许的那样),并且不包含任何换行符、空白或其他附加字符。

CBOR

本规范中的许多结构,包括证明语句和扩展,使用CTAP2规范CBOR编码格式对紧凑二进制对象表示(CBOR)进行编码[RFC8949],如[FIDO-CTAP]中定义的那样。

CDDL

本规范使用CBOR数据定义语言(CDDL[RFC8610]描述所有CBOR编码数据的语法。

COSE

CBOR对象签名和加密(COSE)[RFC8152]。本规范建立的IANA COSE算法注册表[IANA-COSE-ALGS-REG]也被使用。

凭据管理

本文件中描述的API是对Credential 概念的扩展,定义在[CREDENTIAL-MANAGEMENT-1]中。

DOM

DOMException 和本规范中使用的DOMException值定义在[DOM4]中。

ECMAScript

%ArrayBuffer%定义在[ECMAScript]中。

HTML

概念浏览上下文不透明源元组源相关设置对象是可注册的域名后缀或等于[HTML]中定义。

URL

概念同站[URL]中定义。

Web IDL

本规范中的许多接口定义以及所有IDL依赖于[WebIDL]。本次更新的Web IDL标准版本增加了对Promise的支持,现已成为所有新Web API中异步交互的首选机制。

FIDO AppID

用于确定调用应用程序的FacetID确定调用者的FacetID是否被授权用于AppID(仅在AppID扩展中使用)的算法定义在[FIDO-APPID]中。

本文档中的关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“MAY”和“OPTIONAL”的解释如[RFC2119]所述。

4. 术语

证明

一般来说,证明是一种声明,用于作证、确认或认证。在 WebAuthn 的上下文中,证明用于证明一个认证器及其发出的数据的来源;包括例如:凭证 ID凭证密钥对、签名计数器等。证明声明证明对象 中传递,在注册期间。另见§ 6.5 证明图 6客户端如何传递证明声明AAGUID部分的证明对象依赖方,由证明传递描述。

证明证书

用于证明密钥对的 X.509 证书,由身份验证器使用,以证明其 制造和能力。在注册时,身份验证器使用证明 私钥来签名 依赖方特定的凭证公钥(和其他数据),该数据由其生成并通过authenticatorMakeCredential操作返回。依赖方使用 证明公钥,该公钥在证明 证书中传达,用于验证证明签名。注意,在自我证明的情况下,身份验证器没有独特的证明密钥对证明证书,有关详细信息,请参见自我证明

身份验证
身份验证仪式

用户与用户的客户端(至少包含一个身份验证器)共同进行的仪式,通过加密方式向依赖方证明用户控制着先前注册的凭证私钥,该凭证为公钥凭证(参见注册)。请注意,这包括用户存在性测试用户验证

WebAuthn身份验证仪式§ 7.2 验证身份验证声明中定义,由依赖方通过调用navigator.credentials.get() 方法并传入publicKey 参数来启动。有关介绍性概述,请参见§ 5 Web 身份验证 API,以及实现示例请参见§ 1.3.3 身份验证

身份验证断言
断言

身份验证器断言响应 对象返回,该对象由 身份验证器authenticatorGetAssertion 操作的结果。

这对应于 [CREDENTIAL-MANAGEMENT-1] 规范中的一次性 凭证

身份验证器
WebAuthn 身份验证器

一种加密实体,存在于硬件或软件中,能够 注册 用户与给定的 依赖方,并在 后续 声明拥有 注册的 公钥凭证, 并在 依赖方 请求时可选择性地 验证用户身份认证器 可以通过 证明注册 时报告其 类型 和安全特性。

一个 WebAuthn 认证器 可以是一个 漫游认证器, 一个集成到 客户端设备 中的专用硬件子系统, 或者是 客户端客户端设备 的软件组件。

通常,假设一个 认证器 只有一个用户。 如果多个自然人共享对一个 认证器 的访问权, 则它们在该 认证器 的上下文中被视为代表同一个用户。 如果一个 认证器 实现支持多个用户并在不同的隔离区中管理, 那么每个隔离区都被视为一个具有单一用户的独立 认证器,且该用户无法访问其他用户的 凭证

授权手势

一种 授权手势 是用户与身份验证器之间作为 仪式 的一部分进行的物理互动, 例如 注册身份验证。通过 进行这样的 授权手势,用户 提供同意(即 授权仪式的继续。这可能涉及 用户验证,如果所使用的 身份验证器 能够做到这一点,或者可能仅涉及简单的 用户存在性测试

生物识别 识别

基于个体的生物和行为特征的自动识别 [ISOBiometricVocabulary]

生物识别身份验证器

任何实现 生物识别识别身份验证器

绑定 凭证

一个公钥凭证源公钥凭证被称为与其绑定到其管理身份验证器。这意味着只有管理身份验证器可以为与其公钥凭证源 绑定生成断言

仪式

仪式”的概念[Ceremony]是网络协议概念的扩展,包含 人类节点与计算机节点,并且通信链路包括用户界面、人与人之间的通信,以及携带数据的 物理对象的转移。协议外的内容在仪式中是内部的。在本规范中,注册身份验证都是仪式,而授权手势通常是 这些仪式的一部分。

客户端
WebAuthn 客户端

在此也简单称为客户端。另见符合规范的用户代理WebAuthn 客户端是一个中介 实体,通常在用户代理中实现(全部或部分)。概念上,它支持Web 身份验证 API并体现了[[Create]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 内部方法的实现。它 负责为基础身份验证操作 编组输入,并将后者操作的结果返回给Web 身份验证 API的调用者。

WebAuthn 客户端 运行于,并且与WebAuthn 客户端设备不同。

客户端 设备
WebAuthn 客户端设备

运行WebAuthn 客户端的硬件设备,例如智能手机、笔记本 电脑或台式电脑,以及在该硬件上运行的操作系统。

WebAuthn 客户端设备客户端之间的区别是:

客户端设备客户端共同构成客户端平台

客户端平台

一个 客户端设备 和一个 客户端 一起构成一个 客户端平台。 单一硬件设备 MAY 在不同时间通过运行不同的操作系统和/或 客户端 而成为多个 不同的 客户端平台 的一部分。

客户端

这通常是指用户的 客户端平台身份验证器,以及 一切将其串联在一起的事物。

客户端可发现的公钥凭证源
客户端可发现的凭证
可发现的凭证
[已弃用] 驻留凭证
[已弃用] 驻留密钥

注意:历史上,客户端可发现凭证被称为常驻凭证常驻密钥。 由于短语ResidentKeyresidentKeyWebAuthn API以及身份验证器模型中广泛使用(例如,在字典成员名称、算法变量名和操作参数中),因此为了向后兼容,它们的名称中仍使用resident。 此外,术语常驻密钥在此定义为等同于客户端可发现凭证

一个 客户端可发现的公钥凭证源,简称为 可发现凭证, 是一个 公钥凭证源,它是 可发现的,并且可以在 身份验证仪式中使用, 在这种仪式中,依赖方 不提供任何 凭证 ID,即 依赖方 调用 navigator.credentials.get() 并传入一个 allowCredentials 参数。这意味着 依赖方 并不一定需要首先识别用户。

因此,具有可发现凭证能力身份验证器可以仅通过提供断言签名来生成可发现凭证,仅需提供RP ID,这反过来要求将公钥凭证源存储在身份验证器客户端平台中。 这与服务器端公钥凭证源不同,后者要求将身份验证器提供RP ID凭证ID,但不要求在客户端存储公钥凭证源

另见:客户端凭证存储方式不可发现凭证

注意:客户端可发现凭证也可用于身份验证仪式,其中给定了凭证ID, 即在调用navigator.credentials.get() 时,带有非allowCredentials 参数。

符合规范的用户代理

一种用户代理,它与底层的 客户端设备 协作,实施本规范中给出的 Web 身份验证 API 和算法,并处理 身份验证器依赖方 之间的通信。

凭证 ID

一种概率唯一的 字节序列 用于标识 公钥凭证源及其 身份验证断言

凭证 ID 由 身份验证器 生成,形式有两种:

  1. 至少 16 字节,包含至少 100 位的熵,或者

  2. 未包含其 凭证 ID可变项公钥凭证源,加密后仅其 管理身份验证器 可以解密。这种形式使得 身份验证器 几乎是无状态的,通过让 依赖方 存储任何必要的状态。

    注意: [FIDO-UAF-AUTHNR-CMDS] 包含有关加密技术的指导,位于“安全指南”中。

依赖方 无需区分这两种 凭证 ID 形式。

凭证密钥对
凭证私钥
凭证公钥
用户公钥

一个 凭证密钥对 是由 身份验证器 生成的一对非对称加密密钥,并 限制 到特定的 WebAuthn 依赖方。它是 公钥凭证 的核心部分。

一个 凭证公钥凭证密钥对 的公钥部分。 凭证公钥依赖方注册仪式期间返回给它。

一个 凭证私钥凭证密钥对 的私钥部分。 凭证私钥 绑定到特定的 身份验证器 - 其 管理身份验证器 - 并且预期永远不会暴露给任何其他方,甚至不包括 身份验证器 的拥有者。

注意,在 自我认证 的情况下,凭证密钥对 也用作 认证密钥对,详见 自我认证 的详细信息。

注意: 凭证公钥 在 FIDO UAF [UAFProtocol] 中被称为 用户公钥,并且在 FIDO U2F [FIDO-U2F-Message-Formats] 以及与其相关的本规范的某些部分中。

凭证属性

一个凭证属性是一个公钥凭证源的某个特征属性,例如它是否是一个客户端可发现的凭证或一个服务器端凭证

人类可口性

一个被称为 人类可口的 标识符旨在被典型的人类用户记忆和重现,这与那些例如随机生成的位序列的标识符形成对比 [EduPersonObjectClassSpec]

不可发现凭证

这是一个 凭证,其 凭证 ID 必须在 allowCredentials 调用 navigator.credentials.get() 时提供,因为它不是 客户端可发现 的。另见 服务器端凭证

公钥凭证源

凭证源 ([CREDENTIAL-MANAGEMENT-1]) 用于由 认证器 生成 身份验证声明。一个 公钥凭证源 包含一个 结构,其包含以下

类型

其值为 PublicKeyCredentialType, 默认为 public-key

ID

一个 凭证 ID

私钥

凭证私钥

rpId

依赖方标识符,用于该 依赖方, 此 公钥凭证源作用域

用户句柄

与该 公钥凭证源 创建时关联的 用户句柄。 此 是 可为 null 的。

其他用户界面

可选的其他信息,用于 身份验证器 通知其用户界面。例如,这可能包括用户的 显示名称其他用户界面 是一个 可变项,并且 不应以任何方式绑定到 公钥凭证源,以免阻止 其他用户界面 的更新。

The authenticatorMakeCredential operation creates a 公钥凭证源 一个 管理身份验证器 绑定,并返回与其 凭证公钥 相关联的 凭证私钥依赖方 可以使用该 凭证公钥 来验证由该 公钥凭证源 创建的 身份验证声明

公钥凭证

一般而言,凭证是一个实体向另一个实体提供的数据,用以验证前者对后者的身份 [RFC4949]。术语 公钥凭证 指的是以下其中之一:一个 公钥凭证源,可能的证明凭证公钥,该公钥对应于一个 公钥凭证源,或是一个 身份验证断言。具体取决于上下文来决定使用哪一个。

注意:这是对故意违反 [RFC4949]。用英文来说,“凭证”既是 a) 证明声明的东西,也是 b) 打算多次使用的东西。在公钥系统中,无法用单一数据安全地满足这两个条件。[RFC4949] 选择将凭证定义为可以多次使用的东西(公钥),而本规范则赋予“凭证”更多英语术语的灵活性。本规范 使用更具体的术语来识别与[RFC4949]凭证相关的数据:
“身份验证信息”(可能包括私钥)

公钥凭证源

“签名值”

身份验证断言

[RFC4949] “凭证”

凭证公钥证明对象

注册时,身份验证器 创建一个非对称密钥对,并将其私钥部分和来自 依赖方的信息存储在 公钥凭证源中。公钥部分被返回给 依赖方,后者随后将其与当前用户的帐户一起存储。 随后,只有该依赖方(通过其RP ID识别)才能在身份验证仪式中使用公钥凭证,通过 get() 方法。依赖方使用其存储的 凭证公钥来验证结果的身份验证断言

速率限制

身份验证器通过限制在给定时间段内连续失败的身份验证尝试次数来实施对暴力破解攻击的控制的过程(也称为节流)。如果达到限制,身份验证器应施加一个延迟,该延迟随着每次尝试的增加而指数增加,或者禁用当前的身份验证方式,并在可用时提供不同的身份验证因素速率限制通常作为用户验证的一个方面来实施。

注册
注册仪式

用户、依赖方和用户的客户端(至少包含一个身份验证器)协同工作以创建公钥凭证并将其与用户的依赖方帐户关联的仪式。请注意,这包括进行用户存在性测试用户验证。 在成功的注册仪式后,用户可以通过身份验证仪式进行身份验证。

WebAuthn注册仪式§ 7.1 注册新凭证中定义, 并由依赖方调用 navigator.credentials.create() 方法,带有 publicKey 参数。 参见§ 5 Web Authentication API以获取入门概述,以及§ 1.3.1 注册以获取实施示例。

依赖方

参见 WebAuthn 依赖方

依赖方标识符
RP ID

WebAuthn API的上下文中,依赖方标识符是一个有效域字符串,用于识别进行给定注册身份验证仪式WebAuthn依赖方。一个公钥凭证只能用于与其注册的同一实体(通过RP ID识别)进行身份验证

默认情况下,WebAuthn操作的RP ID设置为调用者的来源有效域。此默认值可以被调用者覆盖,只要调用者指定的RP ID是可注册域的后缀或等于调用者的来源有效域。另请参见§ 5.1.3 创建新凭证 - PublicKeyCredential的[[Create]](origin, options, sameOriginWithAncestors)方法§ 5.1.4 使用现有凭证进行断言 - PublicKeyCredential的[[Get]](options)方法

注意:RP ID基于主机名。它本身不包括方案端口,如来源所示。RP ID公钥凭证确定其范围。即,它确定可使用公钥凭证的来源集合,如下所示:

例如,给定一个依赖方,其来源为https://login.example.com:1337,则以下RP ID是有效的:login.example.com(默认)和example.com,但不包括m.login.example.comcom

这样做是为了匹配普遍部署的环境凭证(例如,cookies,[RFC6265])的行为。请注意,这比document.domain的设置器提供的"同源"限制要宽松得多。

这些对来源值的限制适用于WebAuthn客户端

其他规范模仿WebAuthn API以在非Web平台(例如原生移动应用)上启用WebAuthn 公钥凭证,可以定义不同的规则将调用者绑定到依赖方标识符。不过,RP ID 语法必须符合有效域字符串或URI [RFC3986] [URL]

服务器端公钥凭证源
服务器端凭证
[已弃用] 非驻留凭证

注意: 历史上,服务器端凭证 被称为 非驻留凭证。 出于向后兼容的目的,各种形式的 WebAuthn API认证器模型 组件中包含不同形式的 resident 的名称未被更改。

一个 服务器端公钥凭证源,或简称为 服务器端凭证,是一个 公钥凭证源,仅在 身份验证仪式中可用,当 依赖方 提供其 凭证ID 作为 navigator.credentials.get()allowCredentials 参数。这意味着 依赖方 必须管理凭证的存储和发现,并且能够首先识别用户以 发现要在 navigator.credentials.get() 调用中提供的 凭证ID

客户端 存储的 公钥凭证源 对于 服务器端凭证 并不是必需的。 这与 客户端可发现凭证 相对立,后者不需要用户首先被识别以提供用户的 凭证ID 以供 navigator.credentials.get() 调用。

另请参见: 服务器端凭证存储模式不可发现凭证

用户存在测试

A 用户存在测试 是一种简单的 授权手势 和技术过程,用户通过与 身份验证器 进行交互(通常是简单触摸),得出一个布尔结果。注意,这并不构成 用户验证,因为根据定义,用户存在测试 不能进行 生物识别,也不涉及共享密码或 PIN 的呈现。

用户同意

用户同意意味着用户同意他们所被询问的内容,即它涵盖了阅读和理解提示。一种 授权手势 是一种 仪式 组件,通常用于表示 用户同意

用户标识

用户标识由 依赖方 指定,作为 user.id 的值,并用于 映射 特定的 公钥凭证 到特定的用户帐户与 依赖方。身份验证器反过来 映射 RP ID 和用户标识对到 公钥凭证源

用户标识是一个不透明的 字节序列,最大大小为 64 字节,不应显示给用户。

用户验证

技术过程,身份验证器 本地授权 触发 authenticatorMakeCredentialauthenticatorGetAssertion 操作。 用户验证 可以通过多种 授权手势 模式触发;例如,通过触摸加上 PIN 码、密码输入或 生物识别(例如,呈现指纹)[ISOBiometricVocabulary]。目的是区分个体用户。

请注意,用户验证 并不会为 依赖方 提供用户的具体身份识别, 但当使用该 凭证 进行2次或更多次带有 用户验证 的验证仪式时,这表明所有操作都是由同一个用户执行的。 然而,如果多个自然人共享同一个 认证器 的访问权限,则同一用户不一定总是指同一个自然人。

注意: 区分自然人很大程度上取决于 客户端平台身份验证器 的能力。例如,一些设备设计为单个用户使用,但它们可能允许多个自然人注册指纹或知道相同的 PIN,从而使用该设备访问同一 依赖方 帐户。

注意:调用authenticatorMakeCredentialauthenticatorGetAssertion操作意味着使用由认证器管理的密钥材料。

此外,为了安全,用户验证凭证私钥的使用必须全部在定义认证器的逻辑安全边界内进行。

用户验证 程序可以实施 速率限制 作为对抗暴力攻击的保护措施。

用户 在场
UP

在成功完成用户在场测试后,用户被认为是 "在场"。

用户 已验证
UV

在成功完成用户验证过程后,用户被认为是"已验证"。

WebAuthn 依赖方

网络 应用利用Web身份验证API注册验证用户的实体。

一个依赖方 实现通常由一些客户端脚本组成 ,这些脚本在Web身份验证API中调用客户端, 以及执行依赖方操作和其他应用逻辑的服务器端组件。 这两个组件之间的通信必须使用HTTPS或等效的传输安全,但这超出了本规范的范围。

注意:虽然依赖方这个术语在其他上下文中也经常使用(例如X.509和OAuth), 在一个上下文中充当依赖方的实体不一定在其他上下文中也是依赖方。 在本规范中,术语WebAuthn依赖方通常缩写为依赖方, 明确指代WebAuthn上下文中的依赖方。请注意,在任何具体实例中, WebAuthn上下文可能嵌入在更广泛的总体上下文中,例如基于OAuth的上下文。

5. 网络身份验证API

本节规范性地指定了创建和使用公钥凭证的API。基本思想是,这些凭证属于用户,并由管理WebAuthn身份验证器所管理,WebAuthn依赖方通过客户端平台与之交互。依赖方脚本可以在用户同意的情况下,请求浏览器为依赖方创建一个新凭证以供将来使用。请参见下文的

注册流程

脚本还可以请求用户的权限,以使用现有凭证执行身份验证操作。请参见下面的

身份验证流程

所有此类操作均在认证器中执行,并由客户端平台代表用户进行管理。在任何时候,脚本都无法访问凭证本身;它仅能获取有关凭证的对象信息。

除了上述的脚本接口外,认证器还可以实现(或附带客户软件实现)用户管理界面。例如,此界面可用于将认证器重置为干净状态或检查当前的认证器状态。换句话说,这种界面类似于浏览器提供的用户管理界面,用于管理用户状态如历史记录、已保存密码和 cookie。凭证删除等认证器管理操作视为此类用户界面的责任,并刻意不在脚本公开的 API 中包含。

该 API 的安全特性由客户端和认证器共同提供。认证器持有并管理凭证,确保所有操作均限定于特定的来源,并且通过在其响应中包含来源信息,确保操作不会被重新用于不同的来源。具体而言,如在第 6.3 节 认证器操作中定义的那样,当创建新的凭证时,以及在 WebAuthn 凭证生成的所有声明中,请求者的完整来源均被包含并签名在证明对象中。

此外,为了维护用户隐私并防止恶意Relying Parties探测其他Relying Parties所属的公钥凭证的存在,每个凭证也会限定于一个Relying Party Identifier,或称RP ID。该RP ID由客户端在所有操作中提供给认证器,并且认证器确保由某个Relying Party创建的凭证只能在同一RP ID请求的操作中使用。以这种方式将来源RP ID分离,允许在一个Relying Party维护多个来源的情况下使用该 API。

客户端通过为每个操作提供Relying Party来源RP ID认证器来协助这些安全措施。由于这是 WebAuthn 安全模型的一个组成部分,用户代理仅向安全上下文中的调用者公开该 API。特别是对于网络上下文,仅包括通过无错误建立的安全传输(例如 TLS)访问的上下文。

Web 身份验证 API 由以下章节中呈现的 Web IDL 片段的联合定义。综合 IDL 列表见IDL 索引

5.1. PublicKeyCredential 接口

PublicKeyCredential

适用于所有当前引擎。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (旧版)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetOpera Mobile

PublicKeyCredential 接口继承自Credential [CREDENTIAL-MANAGEMENT-1],并包含在创建新凭证或请求新断言时返回给调用者的属性。

PublicKeyCredential/getClientExtensionResults

适用于所有当前引擎。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (旧版)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetOpera Mobile

PublicKeyCredential/rawId

适用于所有当前引擎。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (旧版)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetOpera Mobile
[SecureContext, Exposed=Window]
interface PublicKeyCredential : Credential {
[SameObject] readonly attribute ArrayBuffer              rawId;
[SameObject] readonly attribute AuthenticatorResponse    response;
AuthenticationExtensionsClientOutputs getClientExtensionResults();
};
id

此属性继承自Credential, 不过PublicKeyCredential 覆盖了Credential的getter, 而是返回对象中数据的base64url编码[[identifier]] 内部槽

rawId

此属性返回ArrayBuffer ,包含在[[identifier]] 内部槽中。

PublicKeyCredential/response

适用于所有当前引擎。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (旧版)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetOpera Mobile

response 类型为 AuthenticatorResponse,只读

此属性包含认证器对客户端请求的响应,创建公钥凭证或生成身份验证断言。如果PublicKeyCredential 是响应create()而创建的, 则此属性的值将是AuthenticatorAttestationResponse, 否则, PublicKeyCredential 是响应get()而创建的, 并且此属性的值 将是AuthenticatorAssertionResponse

getClientExtensionResults()

此操作返回[[clientExtensionsResults]]的值, 该值是一个包含映射扩展标识符客户端扩展输出 条目的客户端扩展处理

[[type]]

PublicKeyCredential 接口对象[[type]] 内部槽的值是字符串 "public-key"。

注意:这通过type 继承自Credential的getter进行反映。

[[discovery]]

PublicKeyCredential 接口对象[[discovery]] 内部槽的值为 "remote"。

[[identifier]]

这个 内部槽 包含由认证器选择的 凭证 ID凭证 ID 用于查找可用凭证,因此预期在相同类型的所有凭证中,在所有认证器之间具有高概率的全球唯一性。

注意: 此 API 不限制此标识符的格式或长度,唯一要求是它必须足够让 认证器 唯一选择一个密钥。 例如,某些没有板载存储的认证器可能会创建包含 凭证私钥 的标识符,并使用认证器中烧录的对称密钥进行包装。

[[clientExtensionsResults]]

这个 内部槽 包含处理 依赖方 请求的客户端扩展的结果,这些扩展是在 依赖方 调用 navigator.credentials.create()navigator.credentials.get() 时请求的。

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

5.1.1. CredentialCreationOptions 字典扩展

为了支持通过navigator.credentials.create()进行注册, 本文档扩展了 CredentialCreationOptions 字典如下:

partial dictionary CredentialCreationOptions {
PublicKeyCredentialCreationOptions      publicKey;
};

5.1.2. CredentialRequestOptions 字典扩展

为了支持通过navigator.credentials.get()获取断言, 本文档扩展了CredentialRequestOptions 字典如下:

partial dictionary CredentialRequestOptions {
PublicKeyCredentialRequestOptions      publicKey;
};

5.1.3. 创建一个新的凭证 - PublicKeyCredential的 [[Create]](origin, options, sameOriginWithAncestors) 方法

PublicKeyCredential接口对象的实现 [[Create]](origin, options, sameOriginWithAncestors) 内部方法 [CREDENTIAL-MANAGEMENT-1] 允许 WebAuthn依赖方 脚本调用 navigator.credentials.create() 来请求创建一个新的 公钥凭证源,并 绑定认证器。此 navigator.credentials.create() 操作可以通过利用AbortController中止; 详见 DOM §3.3 在API中使用AbortController和AbortSignal对象 获取详细说明。

内部方法 接受三个参数:

origin

此参数是相关设置对象origin,由 调用create()实现决定。

options

此参数是一个 CredentialCreationOptions 对象,其 options.publicKey 成员包含一个 PublicKeyCredentialCreationOptions 对象,指定要创建的公钥凭证的期望属性。

sameOriginWithAncestors

此参数是一个布尔值,当且仅当调用者的环境设置对象与其祖先同源时为true。如果调用者是跨域的,则为false

注意:内部方法的调用表明它已被权限策略允许,评估于[CREDENTIAL-MANAGEMENT-1]级别。 详见 § 5.9 权限策略集成

注意: 此算法是同步的: Promise 的解决/拒绝由navigator.credentials.create()处理。

注意:此算法中使用的所有BufferSource 对象必须在算法开始时进行快照, 以避免潜在的同步问题。算法实现应获取缓冲源持有的字节的副本并在算法的相关部分中使用该副本。

当调用此方法时,用户代理必须执行以下算法:

  1. 断言: options.publicKey 是存在的。

  2. 如果sameOriginWithAncestorsfalse,则返回 "NotAllowedError" DOMException

    注意:此"sameOriginWithAncestors"限制旨在解决在问题 #1336中提出的跟踪问题。此规范的未来版本可能会对此进行修订。

  3. optionsoptions.publicKey 的值。

  4. 如果 timeout 成员options存在,检查其值是否在客户端定义的合理范围内,如果不在,则将其调整为该范围内的最接近值。将计时器lifetimeTimer设置为此调整后的值。如果timeout 成员options不存在,则将lifetimeTimer设置为客户端特定的默认值。

    对于timeout 成员options的推荐范围和默认值如下: 如果 options.authenticatorSelection.userVerification

    设置为discouraged

    推荐范围:30000 毫秒到 180000 毫秒。

    推荐默认值:120000 毫秒(2 分钟)。

    设置为requiredpreferred

    推荐范围:30000 毫秒到 600000 毫秒。

    推荐默认值:300000 毫秒(5 分钟)。

    注意:用户代理应在考虑具有特殊需求的用户的认知指南后再确定超时。

  5. 如果 options.user.id 的长度不在 1 到 64 字节(含)之间,则返回 TypeError

  6. callerOriginorigin。 如果callerOrigin不透明的origin,则返回一个DOMException 其名称为 "NotAllowedError", 并终止此算法。

  7. effectiveDomaincallerOrigin有效域名。 如果有效域名不是有效域名,则返回一个DOMException 其名称为 "SecurityError", 并终止此算法。

    注意:一个有效域名可以解析为host,其表示形式多种多样, 如域名IPv4 地址IPv6 地址不透明的host空host。 此处仅允许域名格式的host。 这是为了简化,同时也 认识到使用直接IP地址识别与PKI-based安全结合使用的各种问题。

  8. 如果 options.rp.id

    存在

    如果 options.rp.id 不是注册域名后缀或不等于effectiveDomain, 返回一个DOMException 其名称为"SecurityError", 并终止此算法。

    不存在

    options.rp.id 设置为effectiveDomain

    注意: options.rp.id 代表调用者的RP IDRP ID默认情况下为调用者的origineffective domain,除非调用者在调用create()时显式设置了 options.rp.id

  9. credTypesAndPubKeyAlgs为一个新的列表,其PublicKeyCredentialType 和 一个COSEAlgorithmIdentifier

  10. 如果 options.pubKeyCredParams大小

    为零

    附加以下PublicKeyCredentialTypeCOSEAlgorithmIdentifier对到credTypesAndPubKeyAlgs

    非零

    对于每个currentoptions.pubKeyCredParams

    1. 如果 current.type 不包含此实现支持的PublicKeyCredentialType, 则继续

    2. algcurrent.alg

    3. 附加此对 current.typealgcredTypesAndPubKeyAlgs

    如果credTypesAndPubKeyAlgs为空,则返回DOMException 其名称为 "NotSupportedError", 并终止此算法。

  11. clientExtensions为一个新的映射,让authenticatorExtensions为一个新的映射

  12. 如果optionsextensions成员存在,则对于每个 extensionIdclientExtensionInputoptions.extensions

    1. 如果extensionId不被此客户端平台支持或不是注册扩展,则继续

    2. 设置 clientExtensions[extensionId] 为clientExtensionInput

    3. 如果extensionId不是认证器扩展,则继续

    4. authenticatorExtensionInput为运行extensionId客户端扩展处理算法时的(CBOR)结果 在clientExtensionInput上。如果算法返回错误,则继续

    5. 设置 authenticatorExtensions[extensionId] 为 authenticatorExtensionInputbase64url 编码

  13. collectedClientData为一个新的CollectedClientData实例,其字段为:

    type

    字符串 "webauthn.create"。

    challenge

    options 中的 challenge 进行 base64url 编码

    origin

    callerOrigin 进行 序列化

    crossOrigin

    与传递给该 内部方法sameOriginWithAncestors 参数的值的反向。

    tokenBinding

    客户端与 callerOrigin 之间的 Token Binding 状态,以及与 callerOrigin 关联的 Token Binding ID(如果有的话)。

  14. clientDataJSON为从collectedClientData构造的客户端数据的JSON兼容序列化

  15. clientDataHash为由clientDataJSON表示的客户端数据序列化后的哈希值

  16. 如果 options.signal 存在,并且其中止标志设置为true,则返回DOMException 其名称为"AbortError", 并终止此算法。

  17. issuedRequests为一个新的有序集合

  18. authenticators表示一个值,该值在任何给定时刻都是一个有序集合,其中包含客户端平台特定的句柄,每个标识当前此客户端平台上可用的一个认证器

    注意: 什么使认证器被视为"可用"是有意未指定的;这是为了表示如何通过各种机制认证器可以热插拔到(例如,通过USB)或被客户端发现(例如,通过NFC或蓝牙),或永久内置于客户端中。

  19. 启动lifetimeTimer

  20. lifetimeTimer未过期时,依据lifetimeTimer、 状态和响应对于每个 authenticatorauthenticators 中执行以下操作:

    如果lifetimeTimer过期,

    对于每个authenticatorissuedRequests 中调用authenticatorCancel操作,并移除authenticatorissuedRequests中。

    如果用户行使用户代理用户界面选项来取消该过程,

    对于每个authenticatorissuedRequests中调用authenticatorCancel操作,并移除authenticatorissuedRequests中。返回一个DOMException 其名称为 "NotAllowedError"。

    如果 options.signal 存在并且其中止标志设置为true

    对于每个authenticatorissuedRequests中调用authenticatorCancel操作,并移除authenticatorissuedRequests中。然后返回一个DOMException 其名称为"AbortError", 并终止此算法。

    如果authenticator在此客户端设备上变得可用,

    注意:这包括lifetimeTimer启动时authenticator已经可用的情况。

    1. authenticator现在是候选认证器

    2. 如果 options.authenticatorSelection 存在:

      1. 如果 options.authenticatorSelection.authenticatorAttachment 存在且其值不等于authenticator认证器连接方式继续

      2. 如果 options.authenticatorSelection.residentKey

        存在并设置为required

        如果authenticator无法存储客户端可发现的公钥凭证源继续

        存在并设置为preferreddiscouraged

        无效。

        不存在

        如果 options.authenticatorSelection.requireResidentKey 设置为true,且authenticator无法存储客户端可发现的公钥凭证源继续

      3. 如果 options.authenticatorSelection.userVerification 设置为requiredauthenticator无法执行用户验证,则继续

    3. requireResidentKey成为有效的凭证创建的常驻密钥要求,作为一个布尔值,规则如下:

      如果 options.authenticatorSelection.residentKey

      存在并设置为required

      requireResidentKeytrue

      存在并设置为preferred

      如果authenticator

      能够执行客户端凭证存储方式

      requireResidentKeytrue

      无法执行客户端凭证存储方式,或客户端无法确定认证器能力,

      requireResidentKeyfalse

      存在并设置为discouraged

      requireResidentKeyfalse

      不存在

      requireResidentKey为以下值: options.authenticatorSelection.requireResidentKey

    4. userVerification成为有效的凭证创建的用户验证要求,作为一个布尔值,规则如下: 如果 options.authenticatorSelection.userVerification

      设置为required

      userVerificationtrue

      设置为preferred

      如果authenticator

      能够执行用户验证

      userVerificationtrue

      无法执行用户验证

      userVerificationfalse

      设置为discouraged

      userVerificationfalse

    5. enterpriseAttestationPossible成为一个布尔值,规则如下。 如果 options.attestation

      设置为enterprise

      enterpriseAttestationPossibletrue,如果用户代理希望支持企业证明对于 options.rp.id (参见步骤8,在上文中)。 否则设为false

      否则

      enterpriseAttestationPossiblefalse

    6. excludeCredentialDescriptorList为一个新的列表

    7. 对于每个凭证描述符Coptions.excludeCredentials中:

      1. 如果 C.transports 非空,并且 authenticator连接的传输方式不在C.transports中提到,客户端可继续

        注意:如果客户端选择继续,这可能会导致意外注册多个凭证绑定到同一个认证器,如果 C.transports中的传输提示不准确。 例如,存储的传输提示可能会因为软件升级添加了新的连接选项而变得不准确。

      2. 否则,附加CexcludeCredentialDescriptorList中。

      3. authenticator上调用authenticatorMakeCredential操作,并使用clientDataHashoptions.rpoptions.userrequireResidentKeyuserVerificationcredTypesAndPubKeyAlgsexcludeCredentialDescriptorListenterpriseAttestationPossible, 以及authenticatorExtensions作为参数。

    8. 附加authenticatorissuedRequests

    如果authenticator在此客户端设备上不再可用,

    移除authenticatorissuedRequests中。

    如果任何authenticator返回状态指示用户取消了操作,
    1. 移除authenticatorissuedRequests中。

    2. 对于每个剩余的authenticatorissuedRequests中调用authenticatorCancel操作,并移除它从issuedRequests中。

      注意:认证器可能会返回“用户取消了整个操作”的指示。 用户代理如何将此状态显示给用户是未指定的。

    如果任何authenticator返回的错误状态等同于"InvalidStateError",
    1. 移除authenticatorissuedRequests中。

    2. 对于每个剩余的authenticatorissuedRequests中调用authenticatorCancel操作,并移除它从issuedRequests中。

    3. 返回一个DOMException 其名称为"InvalidStateError", 并终止此算法。

    注意:单独处理此错误状态是因为authenticator仅在excludeCredentialDescriptorList标识了绑定到authenticator凭证且用户已同意该操作时返回该状态。鉴于此明确的同意,此情况可被依赖方区分是可以接受的。

    如果任何authenticator返回的错误状态不等同于"InvalidStateError",

    移除 认证器已发出的请求中。

    注意:此情况并不意味着 用户同意 操作,因此为了防止泄露潜在的身份识别信息,关于错误的详细信息将对 依赖方 隐藏。详情请参见 § 14.5.1 注册仪式隐私

    如果任何authenticator指示成功,
    1. 移除authenticatorissuedRequests中。此认证器现在是已选认证器

    2. credentialCreationData为一个结构体, 其中的为:

      attestationObjectResult

      其值为从成功的authenticatorMakeCredential 操作返回的字节。

      注意:此值为 attObj,如在§ 6.5.4 生成证明对象中定义。

      clientDataJSONResult

      其值为clientDataJSON的字节。

      attestationConveyancePreferenceOption

      其值为optionsattestation的值。

      clientExtensionResults

      其值为一个AuthenticationExtensionsClientOutputs 对象,包含扩展标识符客户端扩展输出 条目。条目是通过运行每个扩展的客户端扩展处理算法来创建客户端扩展输出,对于 optionsextensions中的每个客户端扩展

    3. constructCredentialAlg成为一个算法,该算法接受一个全局对象global, 其步骤为:

      1. 如果 credentialCreationDataattestationConveyancePreferenceOption的值为

        "none"

        将潜在的唯一标识信息替换为相同的非标识版本:

        1. 如果 AAGUID验证过的凭据数据 中是 16 个零字节,且 credentialCreationData.attestationObjectResult.fmt 为 "packed",且 credentialCreationData.attestationObjectResult 中没有 "x5c",那么说明使用了 自我证明,无需采取进一步的操作。

        2. 否则:

          1. AAGUID验证过的凭据数据 中替换为 16 个零字节。

          2. credentialCreationData.attestationObjectResult.fmt 的值设置为 "none",并将 credentialCreationData.attestationObjectResult.attStmt 的值设置为空的 CBOR 映射。(请参阅 § 8.7 无证明声明格式§ 6.5.4 生成证明对象)。

        "indirect"

        客户端可以用更隐私友好和/或更易验证的版本替换 AAGUID证明声明(例如,通过使用 匿名化 CA)。

        "direct" 或 "enterprise"

        身份验证器AAGUID证明声明 原样传递给 依赖方

      2. attestationObject为一个新的ArrayBuffer, 使用global%ArrayBuffer%创建, 包含 credentialCreationDataattestationObjectResult的值的字节。

      3. idattestationObject.authData.attestedCredentialData.credentialId

      4. pubKeyCred为一个新的PublicKeyCredential 对象,与global相关联,其字段为:

        [[identifier]]

        id

        response

        一个新的AuthenticatorAttestationResponse 对象,与global相关联,其字段为:

        clientDataJSON

        一个新的ArrayBuffer, 使用global%ArrayBuffer%创建, 包含 credentialCreationDataclientDataJSONResult的字节。

        attestationObject

        attestationObject

        [[transports]]

        一个或多个唯一的DOMString的序列, 按字典序排列,authenticator被认为支持这些值。 值应该是AuthenticatorTransport的成员, 但客户端平台必须忽略未知的值。

        如果用户代理不希望透露此信息,则可以用设计用来保护隐私的任意序列代替。此序列仍必须有效,即按字典顺序排列且不重复。例如,它可以使用空序列。无论哪种方式,在这种情况下,用户代理需要承担Relying Party行为可能不理想的风险。

        如果用户代理没有任何传输信息,它应将此字段设置为空序列。

        注意:用户代理如何发现给定认证器支持的传输方式超出了本规范的范围,但可能包括来自认证证书的信息(例如[FIDO-Transports-Ext])、在CTAP2等认证器协议中传递的元数据,或关于平台认证器的特殊情况知识。

        [[clientExtensionsResults]]

        一个新的ArrayBuffer, 使用global%ArrayBuffer%创建, 包含 credentialCreationDataclientExtensionResults的字节。

      5. 返回pubKeyCred

    4. 对于每个剩余的authenticatorissuedRequests中调用authenticatorCancel操作,并移除它从issuedRequests中。

    5. 返回constructCredentialAlg并终止此算法。

  21. 返回一个DOMException 其名称为"NotAllowedError"。 为了防止在没有用户同意的情况下泄露可能识别用户的信息, 此步骤必须在lifetimeTimer过期之前不执行。 参见§ 14.5.1 注册仪式隐私了解详细信息。

在上述过程中,用户代理应向用户展示一些UI,以指导他们选择和授权认证器的过程。

5.1.4. 使用现有凭证进行断言 - PublicKeyCredential 的 [[Get]](options) 方法

WebAuthn 依赖方调用 navigator.credentials.get({publicKey:..., ...}) 来发现并使用现有的 公钥凭证,需要获得用户的同意依赖方脚本可以选择指定一些 条件,指明哪些凭证来源是可接受的。客户端平台 定位符合指定条件的凭证来源,并引导 用户选择一个脚本允许使用的凭证。即使存在凭证来源,用户也可能选择拒绝整个交互,例如为了保护隐私。 如果用户选择了一个凭证来源,则用户代理会使用 § 6.3.3 认证器GetAssertion操作来签署由依赖方提供的挑战和其他收集的数据,将其作为一个凭证使用。

get() 实现 [CREDENTIAL-MANAGEMENT-1] 调用 PublicKeyCredential.[[CollectFromCredentialStore]]() 来收集任何凭证,这些凭证应在不需要用户干预的情况下可用(大致相当于本规范的授权手势),如果未找到 符合条件的凭证,则会调用 PublicKeyCredential.[[DiscoverFromExternalSource]]() 让 用户选择一个凭证来源

由于本规范要求在创建任何授权手势时需要进行凭证创建, PublicKeyCredential.[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 内部方法继承了 默认行为 Credential.[[CollectFromCredentialStore]](), 返回一个空集合。

navigator.credentials.get() 操作可以通过使用 AbortController中止; 详见 DOM §3.3 使用 AbortController 和 AbortSignal 对象在 API 中的集成 以获取详细说明。

5.1.4.1. PublicKeyCredential 的 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 方法

这个 内部方法接受三个参数:

origin

这个参数是相关设置对象origin,由调用的get() 实现决定,即CredentialsContainer请求Credential抽象操作。

options

这个参数是一个 CredentialRequestOptions 对象,其中 options.publicKey 成员包含一个 PublicKeyCredentialRequestOptions 对象,指定要发现的 公钥凭证的期望属性。

sameOriginWithAncestors

这个参数是一个布尔值,当且仅当调用者的环境设置对象与其祖先同源时,它为true。如果调用者是跨源的,则它为false

注意: 调用这个 内部方法 表明它已被权限策略允许,该策略在 [CREDENTIAL-MANAGEMENT-1] 级别进行评估。 参见§ 5.9 权限策略集成

注意: 该算法是同步的: Promise 的解决/拒绝由navigator.credentials.get() 处理。

注意: 在此算法中使用的所有 BufferSource 对象必须在算法开始时进行快照,以避免潜在的同步问题。算法实现应获取缓冲区源所持有的字节的副本并在算法的相关部分使用该副本。

调用此方法时,用户代理必须执行以下算法:

  1. 断言: options.publicKey 已存在。

  2. optionsoptions.publicKey 的值。

  3. 如果 timeout 成员出现在 options 中,检查其值是否在由 客户端定义的合理范围内,如果不在该范围内,将其校正为位于该范围内的最接近值。 将计时器 lifetimeTimer 设置为此调整后的值。如果 timeout 成员未出现在 options 中,则将 lifetimeTimer 设置为 客户端特定的默认值。

    timeout 成员的推荐范围和默认值如下。 如果 options.userVerification

    设置为discouraged

    推荐范围:30000 毫秒到 180000 毫秒。

    推荐默认值:120000 毫秒(2 分钟)。

    设置为 requiredpreferred

    推荐范围:30000 毫秒到 600000 毫秒。

    推荐默认值:300000 毫秒(5 分钟)。

    注意: 用户代理应考虑认知指南,针对有特殊需求的用户设置超时时间。

  4. callerOriginorigin。 如果 callerOrigin 是一个不透明的 origin,则返回 DOMException, 其名称为 "NotAllowedError", 并终止此算法。

  5. effectiveDomaincallerOrigin有效域。 如果 有效域 不是一个有效域,则返回 DOMException ,其名称为 "SecurityError" 并终止此算法。

    注意: 有效域可能解析为一个host,它可以通过各种方式表示,如 ipv4 地址ipv6 地址不透明的 host、 或空的 host。 这里只允许 格式的 host。 这是为了简化操作,并且也认识到使用基于 PKI 的安全性与直接 IP 地址识别的各种问题。

  6. 如果 options.rpId 未出现,则将 rpId 设置为 effectiveDomain

    否则:

    1. 如果 options.rpId 不是 effectiveDomain 的可注册域后缀或与其相等,则返回 DOMException, 其名称为 "SecurityError", 并终止此算法。

    2. rpId 设置为 options.rpId 的值。

      注意: rpId 表示调用者的 RP IDRP ID 默认是调用者的 origin有效域,除非调用者在调用get()时显式设置了 options.rpId

  7. clientExtensions 为一个新的 映射,并且 令 authenticatorExtensions 为一个新的 映射

  8. 如果 extensions 成员出现在 options 中,则为每个 extensionIdclientExtensionInputoptions.extensions

    1. 如果 extensionId 不受此客户端平台支持或不是认证扩展,则继续

    2. 设置 clientExtensions[extensionId] 为 clientExtensionInput

    3. 如果 extensionId 不是认证器扩展,则继续

    4. authenticatorExtensionInput 为执行 extensionId客户端扩展处理 算法 在 clientExtensionInput 上的结果(CBOR)。如果算法返回了错误,继续

    5. 设置 authenticatorExtensions[extensionId] 为 base64url 编码authenticatorExtensionInput

  9. collectedClientData 为一个新的 CollectedClientData 实例,其字段如下:

    type

    字符串 "webauthn.get"。

    challenge

    base64url 编码options.challenge

    origin

    origin 的序列化 的值 callerOrigin

    crossOrigin

    与传递给此 内部方法 的参数sameOriginWithAncestors 的值相反。

    tokenBinding

    客户端与 callerOrigin 之间的 Token Binding 的状态,以及与 callerOrigin 关联的 Token Binding ID,如果存在的话。

  10. clientDataJSON客户端数据的 JSON 兼容序列化的表示形式 collectedClientData

  11. clientDataHash序列化客户端数据的哈希值 clientDataJSON

  12. 如果 options.signal 出现并且其aborted 标志被设置为true, 则返回 DOMException, 其名称为 "AbortError", 并终止此算法。

  13. issuedRequests 为一个新的有序集合

  14. savedCredentialIds 为一个新的 映射

  15. authenticators表示一个在任何给定时刻都是一的值,其中包含特定于客户端平台的句柄,每个标识此时在该客户端平台上可用的认证器

    注意:什么使认证器被视为“可用”是故意未具体说明的;这意味着认证器可以通过各种机制被热插拔(例如,通过USB)或被客户端发现(例如,通过NFC或蓝牙),或者永久性地内置于客户端中。

  16. 启动 lifetimeTimer

  17. lifetimeTimer 未过期时, 执行 以下操作,取决于 lifetimeTimer, 以及状态和响应 每个 authenticatorauthenticators 中:

    如果 lifetimeTimer 过期,

    对每个 authenticatorissuedRequests 中调用 authenticatorCancel 操作并且移除 authenticatorissuedRequests 中。

    如果用户执行用户代理用户界面选项以取消过程,

    对每个 authenticatorissuedRequests 中调用 authenticatorCancel 操作并且移除 authenticatorissuedRequests 中。返回 DOMException ,其名称为 "NotAllowedError"。

    如果 signal 成员存在并且 aborted 标志 设置为 true

    对每个 authenticatorissuedRequests 中调用 authenticatorCancel 操作并且移除 authenticatorissuedRequests 中。然后 返回 DOMException, 其名称为 "AbortError", 并终止此算法。

    如果 issuedRequests 为空, options.allowCredentials 不为空,并且没有 authenticator 会变得可用用于其中的任何 公钥凭证

    向用户表明没有找到符合条件的凭证。当用户确认对话框后,返回 DOMException, 其名称为 "NotAllowedError"。

    注意: 一个客户端平台可以确定没有 authenticator 会变得可用的一种方法是检查当前的 transports 成员 的 PublicKeyCredentialDescriptor options.allowCredentials, 如果有的话。例如,如果所有 PublicKeyCredentialDescriptor 仅列出 internal, 但是所有平台 authenticator 都已经尝试过,那么就没有可能满足请求。或者, 所有 PublicKeyCredentialDescriptor 可能列出 transports, 而客户端平台不支持这些 transports。

    如果 authenticator 变得在此客户端设备上可用,

    注意: 这包括 authenticatorlifetimeTimer 启动时已可用的情况。

    1. 如果 options.userVerification 设置为required 并且 authenticator 无法执行 用户验证继续

    2. userVerification有效用户验证要求,一个布尔值,如下所示。如果 options.userVerification

      设置为 required

      userVerificationtrue

      设置为 preferred

      如果 authenticator

      能够执行 用户验证

      userVerificationtrue

      无法执行 用户验证

      userVerificationfalse

      设置为 discouraged

      userVerificationfalse

    3. 如果 options.allowCredentials

      不为空
      1. allowCredentialDescriptorList 成为一个新的 列表

      2. 执行一个特定于 客户端平台 的过程,以确定由 options.allowCredentials 描述的哪些(如果有的话)公钥凭证绑定 到此 authenticator 的,通过与 rpIdoptions.allowCredentials.idoptions.allowCredentials.type 匹配。将 allowCredentialDescriptorList 设置为此筛选后的列表。

      3. 如果 allowCredentialDescriptorList 为空继续

      4. distinctTransports 成为一个新的 有序集合

      5. 如果 allowCredentialDescriptorList 仅有一个值,将 savedCredentialIds[authenticator] 设置为 allowCredentialDescriptorList[0].id 的值(详细信息请参见 此处,位于 § 6.3.3 The authenticatorGetAssertion 操作)。

      6. 对于 allowCredentialDescriptorList 中的每个凭证描述符 C C.transports 的每个值(如果有的话)添加到 distinctTransports 中。

        注: 这将仅聚合 transports 的不同值(对于这个 身份验证器)到 distinctTransports 中,这是由于 有序集合 的属性。

      7. 如果 distinctTransports

        不为空

        客户端从 distinctTransports 中选择一个 transport 值,可能根据与 authenticator 一起使用的适当传输的本地配置知识来做出选择。

        然后,使用 transport,在 authenticator 上调用 authenticatorGetAssertion 操作,参数为 rpIdclientDataHashallowCredentialDescriptorListuserVerificationauthenticatorExtensions

        为空

        根据与 authenticator 一起使用的适当传输的本地配置知识,在 authenticator 上调用 authenticatorGetAssertion 操作,参数为 rpIdclientDataHashallowCredentialDescriptorListuserVerificationauthenticatorExtensions

      为空

      使用本地配置知识选择适合于与 authenticator 配合使用的传输,调用 authenticatorGetAssertion 操作在 authenticator 上,带有 rpIdclientDataHashuserVerificationauthenticatorExtensions 作为参数。

      注意:在此情况下,Relying Party未提供可接受的凭证描述符列表。因此,请求认证器使用它可能拥有的任何限定于通过rpId标识的Relying Party的凭证。

    4. 附加 authenticatorissuedRequests

    如果 authenticator 不再在此客户端设备上可用,

    移除 authenticatorissuedRequests 中。

    如果任何 authenticator 返回一个状态,表示用户取消了操作,
    1. 移除 authenticatorissuedRequests 中。

    2. 对每个 剩余 authenticatorissuedRequests 中调用 authenticatorCancel 操作 并且 移除它从 issuedRequests 中。

      注意: 认证器 可能 返回表示“用户取消了整个操作”的状态。 用户代理如何将此状态表现给用户未做具体说明。

    如果任何 authenticator 返回错误状态,

    移除 authenticatorissuedRequests 中。

    如果任何 authenticator 指示成功,
    1. 移除 authenticatorissuedRequests 中。

    2. assertionCreationData 为一个 结构 ,其 如下所示:

      credentialIdResult

      如果 savedCredentialIds[authenticator] 存在,将credentialIdResult 的值设置为 savedCredentialIds[authenticator] 的字节数。 否则,将credentialIdResult 的值设置为从成功返回的 凭证 ID 的字节数authenticatorGetAssertion操作,在 § 6.3.3 认证器获取断言操作中定义的。

      clientDataJSONResult

      其值为 clientDataJSON 的字节数。

      authenticatorDataResult

      其值为 认证器数据 的字节数,该数据由 认证器 返回。

      signatureResult

      其值为 认证器 返回的签名值的字节数。

      userHandleResult

      如果认证器 返回了一个用户句柄,将 userHandleResult 的值设置为 返回的 用户句柄 的字节数。否则,将 userHandleResult 的值设置为 null。

      clientExtensionResults

      其值为一个AuthenticationExtensionsClientOutputs 对象,包含 扩展标识符客户端扩展输出 条目。条目是通过运行每个扩展的客户端扩展处理 算法创建的 客户端扩展输出, 对于 客户端扩展 中的每个 options.extensions

    3. constructAssertionAlg 为一个算法,它接收一个全局对象 global,其步骤如下:

      1. pubKeyCred 为一个新的 PublicKeyCredential 对象,与 global 关联,其字段如下:

        [[identifier]]

        一个新的 ArrayBuffer ,使用 global%ArrayBuffer% 创建,包含 assertionCreationData.credentialIdResult 的字节数。

        response

        一个新的 AuthenticatorAssertionResponse 对象,与 global 关联,其字段如下:

        clientDataJSON

        一个新的 ArrayBuffer ,使用 global%ArrayBuffer% 创建,包含 assertionCreationData.clientDataJSONResult 的字节数。

        authenticatorData

        一个新的 ArrayBuffer ,使用 global%ArrayBuffer% 创建,包含 assertionCreationData.authenticatorDataResult 的字节数。

        signature

        一个新的 ArrayBuffer ,使用 global%ArrayBuffer% 创建,包含 assertionCreationData.signatureResult 的字节数。

        userHandle

        如果assertionCreationData.userHandleResult为null,则将此字段设置为null。否则,将此字段设置为一个新的ArrayBuffer,使用global%ArrayBuffer%创建,包含assertionCreationData.userHandleResult的字节。

        [[clientExtensionsResults]]

        一个新的 ArrayBuffer ,使用 global%ArrayBuffer% 创建,包含 assertionCreationData.clientExtensionResults 的字节数。

      2. 返回 pubKeyCred

    4. 对每个 剩余 authenticatorissuedRequests 中调用 authenticatorCancel 操作 并且 移除它从 issuedRequests 中。

    5. 返回 constructAssertionAlg 并终止此算法。

  18. 返回 DOMException, 其名称为 "NotAllowedError"。 为了防止泄露可能在未经用户同意的情况下识别用户的信息,此步骤不得在 lifetimeTimer 到期之前执行。有关详细信息,请参见 § 14.5.2 认证隐私

在上述过程中,用户代理应向用户显示一些 UI,以指导他们完成选择和授权一个认证器以完成操作的过程。

5.1.5. 存储现有凭证 - PublicKeyCredential 的 [[Store]](credential, sameOriginWithAncestors) 方法

[[Store]](credential, sameOriginWithAncestors) 方法不支持 Web Authentication 的 PublicKeyCredential 类型,因此它总是返回一个错误。

注意: 该算法是同步的;Promise 的解决/拒绝由 navigator.credentials.store() 处理。

内部方法 接受两个参数:

credential

该参数是一个 PublicKeyCredential 对象。

sameOriginWithAncestors

该参数是一个布尔值,只有当调用者的 环境设置对象 与其祖先 同源 时,值才为 true

当调用此方法时,用户代理必须执行以下算法:

  1. 返回一个 DOMException 其名称为 "NotSupportedError", 并终止此算法。

5.1.6. 防止静默访问现有凭证 - PublicKeyCredential 的 [[preventSilentAccess]](credential, sameOriginWithAncestors) 方法

调用 [[preventSilentAccess]](credential, sameOriginWithAncestors) 方法对需要 授权手势的认证器没有影响,但设置该标志可能会排除那些可以在没有用户干预的情况下操作的认证器。

这个内部方法不接受任何参数。

5.1.7. 用户验证平台认证器的可用性 - PublicKeyCredential 的 isUserVerifyingPlatformAuthenticatorAvailable() 方法

WebAuthn 依赖方使用此方法来确定他们是否可以使用用户验证平台认证器创建新凭证。 调用后,客户端使用 客户端平台特定过程发现可用的用户验证平台认证器。 如果发现任何认证器,promise 的值将解析为 true。 否则,promise 的值将解析为 false。 基于结果,依赖方可以采取进一步行动引导用户创建凭证。

此方法不接受任何参数,并返回一个布尔值。

PublicKeyCredential/isUserVerifyingPlatformAuthenticatorAvailable

在所有当前引擎中可用。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (旧版)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetOpera Mobile
partial interface PublicKeyCredential {
    static Promise<boolean> isUserVerifyingPlatformAuthenticatorAvailable();
};

注意: 从一个 浏览上下文 中调用此方法,而该上下文中的 Web 身份验证 API 根据 允许使用 算法被“禁用”,即通过权限策略,将导致 promise 被拒绝,并抛出 DOMException, 其名称为 "NotAllowedError"。 另见 § 5.9 权限策略集成

5.2. 认证器响应 (接口 AuthenticatorResponse)

AuthenticatorResponse

在所有当前引擎中可用。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (旧版)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetOpera Mobile

认证器通过返回一个从 AuthenticatorResponse 接口派生的对象来响应 依赖方 的请求:

[SecureContext, Exposed=Window]
interface AuthenticatorResponse {
    [SameObject] readonly attribute ArrayBuffer      clientDataJSON;
};

AuthenticatorResponse/clientDataJSON

在所有当前引擎中可用。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (旧版)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetOpera Mobile

clientDataJSON, 类型为 ArrayBuffer, 只读

该属性包含 与 JSON 兼容的序列化客户端数据,其 散列值 是由客户端在调用 create()get() 时传递给认证器的(即,客户端数据本身不会发送给认证器)。

5.2.1. 公钥凭证信息 (接口 AuthenticatorAttestationResponse)

AuthenticatorAttestationResponse

在所有当前引擎中可用。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (旧版)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung Internet10.0+Opera Mobile

AuthenticatorAttestationResponse 接口表示 认证器 对客户端请求创建新 公钥凭证 的响应。它包含有关新凭证的信息,可用于 以后识别它,以及 WebAuthn 依赖方 在注册过程中用来评估凭证特征的元数据。

AuthenticatorAttestationResponse/getTransports

在无当前引擎中可用。

FirefoxSafariChrome
OperaEdge
Edge (旧版)IE
Firefox for AndroidiOS SafariChrome for AndroidAndroid WebViewSamsung InternetOpera Mobile
[SecureContext, Exposed=Window]
interface AuthenticatorAttestationResponse : AuthenticatorResponse {
    [SameObject] readonly attribute ArrayBuffer      attestationObject;
    sequence<DOMString>                              getTransports();
    ArrayBuffer                                      getAuthenticatorData();
    ArrayBuffer?                                     getPublicKey();
    COSEAlgorithmIdentifier                          getPublicKeyAlgorithm();
};
clientDataJSON

此属性继承自AuthenticatorResponse,包含传递给身份验证器的JSON兼容的客户端数据序列化(见§ 6.5 声明),以生成此凭证。确切的JSON序列化必须保持不变,因为序列化客户端数据的哈希是基于它计算的。

AuthenticatorAttestationResponse/attestationObject

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
OperaEdge79+
Edge (Legacy)18IE
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung Internet10.0+Opera Mobile

attestationObject类型为ArrayBuffer,只读

此属性包含一个声明对象,该对象对于客户端是不可见的,并且在加密上受到保护,以防篡改。声明对象包含身份验证器数据声明语句。前者包含AAGUID、唯一的凭证ID以及凭证公钥声明语句的内容由声明语句格式决定,该格式由身份验证器使用。它还包含任何附加信息,该信息是依赖方的服务器所需的,以验证声明语句,以及解码和验证身份验证器数据JSON兼容的客户端数据序列化。更多详细信息,请参见§ 6.5 声明§ 6.5.4 生成声明对象图6

getTransports()

此操作返回[[transports]]的值。

getAuthenticatorData()

此操作返回包含在attestationObject中的身份验证器数据。有关详细信息,请参见§ 5.2.1.1 轻松访问凭证数据

getPublicKey()

此操作返回新的凭证的DERSubjectPublicKeyInfo,如果不可用则返回null。有关详细信息,请参见§ 5.2.1.1 轻松访问凭证数据

getPublicKeyAlgorithm()

此操作返回新凭证的COSEAlgorithmIdentifier。有关详细信息,请参见§ 5.2.1.1 轻松访问凭证数据

[[transports]]

内部插槽包含零个或多个唯一的DOMString的序列,按字典顺序排列。这些值是被认为由身份验证器支持的传输方式,如果信息不可用,则为一个空序列。这些值应为AuthenticatorTransport的成员,但依赖方必须忽略未知值。

5.2.1.1. 轻松访问凭证数据

每个使用 [[Create]](origin, options, sameOriginWithAncestors) 方法的用户都需要解析并存储返回的 凭证公钥,以便验证未来的 认证断言。然而,凭证公钥 位于 [RFC8152] (COSE) 格式中, 在 credentialPublicKey 成员中, 位于 attestedCredentialData 内, 位于 认证器数据 内, 位于 认证对象 内,由 AuthenticatorAttestationResponseattestationObject 传递。 希望使用 认证依赖方 必须解析 attestationObject 并获取 凭证公钥,因为那是由 认证器 签署 的公钥副本。然而,许多有效的 WebAuthn 用例并不需要 认证。 对于这些用途,用户代理可以解析工作,直接公开 认证器数据,并将 凭证公钥 转换为更方便的格式。

因此,getPublicKey() 操作返回 凭证公钥 作为 SubjectPublicKeyInfo。这个 ArrayBuffer 例如可以传递给 Java 的 java.security.spec.X509EncodedKeySpec、.NET 的 System.Security.Cryptography.ECDsa.ImportSubjectPublicKeyInfo 或 Go 的 crypto/x509.ParsePKIXPublicKey

使用 getPublicKey() 确实带来一些限制:通过使用 pubKeyCredParams依赖方 可以与 认证器 协商 使用用户代理可能无法理解的公钥算法。然而,如果 依赖方 这样做,用户代理将无法将生成的 凭证公钥 转换为 SubjectPublicKeyInfo 格式,getPublicKey() 的返回值将为 null。

凭证公钥COSEAlgorithmIdentifier 值为以下值时,用户代理必须能够为 getPublicKey() 返回非 null 值:

SubjectPublicKeyInfo 不包含 COSE 公钥中包含的签名算法信息(例如,使用哪个哈希函数)。 为提供此信息,getPublicKeyAlgorithm() 返回 凭证公钥COSEAlgorithmIdentifier

为了在许多情况下完全消除解析 CBOR 的需求,getAuthenticatorData() 返回 attestationObject 中的 认证器数据认证器数据 包含以二进制格式编码的其他字段。 然而,未提供辅助函数来访问它们,因为 依赖方 已经需要在 获取断言 时提取这些字段。 与 创建凭证 不同,签名验证是 可选的依赖方 应始终验证来自断言的签名,因此必须从签名的 认证器数据 中提取字段。 在此处使用的相同函数也将在创建凭证过程中提供服务。

注意: getPublicKey()getAuthenticatorData() 仅在本规范的第二级中添加。依赖方 应在使用这些函数之前进行功能检测,方法是测试 'getPublicKey' in AuthenticatorAttestationResponse.prototype 的值。 需要此功能存在的 依赖方 可能无法与较旧的用户代理互操作。

5.2.2. Web 认证断言 (接口 AuthenticatorAssertionResponse)

AuthenticatorAssertionResponse

在所有当前的引擎中。

Firefox60+Safari13+Chrome67+
OperaNoneEdge79+
Edge (Legacy)18IENone
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetNoneOpera MobileNone

AuthenticatorAssertionResponse 接口表示 认证器 对客户端请求生成新的 身份验证声明 的响应,该请求包含 WebAuthn 依赖方 的挑战和其已知的凭证列表(可选)。该响应包含一个加密签名,用于证明拥有 凭证私钥,并且可选地包含 用户同意 进行特定交易的证据。

[SecureContext, Exposed=Window]
interface AuthenticatorAssertionResponse : AuthenticatorResponse {
    [SameObject] readonly attribute ArrayBuffer      authenticatorData;
    [SameObject] readonly attribute ArrayBuffer      signature;
    [SameObject] readonly attribute ArrayBuffer?     userHandle;
};
clientDataJSON

AuthenticatorResponse 继承的该属性包含传递给认证器以生成该断言的 与 JSON 兼容的客户端数据序列化(见 § 5.8.1 用于 WebAuthn 签名的客户端数据(词典 CollectedClientData))。 必须保留精确的 JSON 序列化格式,因为已经计算了 已序列化客户端数据的哈希值

AuthenticatorAssertionResponse/authenticatorData

在所有当前的引擎中。

Firefox60+Safari13+Chrome67+
OperaNoneEdge79+
Edge (Legacy)18IENone
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetNoneOpera MobileNone

authenticatorData, 类型为 ArrayBuffer,只读

该属性包含由认证器返回的 认证器数据。参见 § 6.1 认证器数据

AuthenticatorAssertionResponse/signature

在所有当前的引擎中。

Firefox60+Safari13+Chrome67+
OperaNoneEdge79+
Edge (Legacy)18IENone
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetNoneOpera MobileNone

signature, 类型为 ArrayBuffer,只读

该属性包含由认证器返回的原始签名。参见 § 6.3.3 认证器获取断言操作

AuthenticatorAssertionResponse/userHandle

在所有当前的引擎中。

Firefox60+Safari13+Chrome67+
OperaNoneEdge79+
Edge (Legacy)18IENone
Firefox for Android60+iOS Safari13.3+Chrome for Android70+Android WebView70+Samsung InternetNoneOpera MobileNone

userHandle, 类型为 ArrayBuffer,只读,可为空

该属性包含由认证器返回的 用户句柄,如果认证器未返回 用户句柄,则为 null。参见 § 6.3.3 认证器获取断言操作

5.3. 凭证生成参数 (字典 PublicKeyCredentialParameters)

dictionary PublicKeyCredentialParameters {
    required DOMString                    type;
    required COSEAlgorithmIdentifier      alg;
};
此字典用于在创建新凭证时提供额外的参数。
type, 类型为 DOMString

该成员指定要创建的凭证类型。值应为 PublicKeyCredentialType 的成员,但 客户端平台必须忽略未知的值,忽略任何具有未知 PublicKeyCredentialParameterstype

alg, 类型为 COSEAlgorithmIdentifier

该成员指定新生成凭证将使用的加密签名算法,因此也指定了要生成的非对称密钥对的类型,例如 RSA 或椭圆曲线。

注意: 我们使用“alg”作为后一个成员名称,而不是拼出“algorithm”,因为它将被序列化为发给认证器的消息,这可能通过低带宽链接发送。

5.4. 凭证创建选项(字典 PublicKeyCredentialCreationOptions

PublicKeyCredentialCreationOptions

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS 版 Safari13.3+Android 版 Chrome67+Android WebView三星互联网Opera Mobile48+
dictionary PublicKeyCredentialCreationOptions {
    required PublicKeyCredentialRpEntity         rp;
    required PublicKeyCredentialUserEntity       user;

    required BufferSource                             challenge;
    required sequence<PublicKeyCredentialParameters>  pubKeyCredParams;

    unsigned long                                timeout;
    sequence<PublicKeyCredentialDescriptor>      excludeCredentials = [];
    AuthenticatorSelectionCriteria               authenticatorSelection;
    DOMString                                    attestation = "none";
    AuthenticationExtensionsClientInputs         extensions;
};

PublicKeyCredentialCreationOptions/rp

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS Safari13.3+Android 版 Chrome67+Android WebView三星 InternetOpera Mobile48+

rp, 类型为 PublicKeyCredentialRpEntity

此成员包含有关发出请求的 依赖方 的数据。

其值的 name 成员是必需的。有关详细信息,请参阅 § 5.4.1 公钥实体描述(字典 PublicKeyCredentialEntity)

其值的 id 成员指定了应将凭证 限定 为的 RP ID。如果省略, 其值将是 CredentialsContainer 对象的 相关设置对象来源有效域。有关详细信息,请参阅 § 5.4.2 凭证生成的依赖方参数(字典 PublicKeyCredentialRpEntity)

PublicKeyCredentialCreationOptions/user

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS Safari13.3+Android 版 Chrome67+Android WebView三星 InternetOpera Mobile48+

user, 类型 为 PublicKeyCredentialUserEntity

此成员包含有关 依赖方 请求 的用户帐户的 数据。

其值的 namedisplayNameid 成员是必需的。有关详细信息,请参阅 § 5.4.1 公钥实体描述(字典 PublicKeyCredentialEntity)§ 5.4.3 用户帐户凭证生成参数(字典 PublicKeyCredentialUserEntity)

PublicKeyCredentialCreationOptions/challenge

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS Safari13.3+Android 版 Chrome67+Android WebView三星 InternetOpera Mobile48+

challenge, 类型为 BufferSource

此成员包含用于生成新创建的凭证的 证明对象 的挑战。有关安全性注意事项,请参阅 § 13.4.3 加密挑战

PublicKeyCredentialCreationOptions/pubKeyCredParams

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS Safari13.3+Android 版 Chrome67+Android WebView三星 InternetOpera Mobile48+

pubKeyCredParams, 类型为 sequence<PublicKeyCredentialParameters>

此成员包含有关要创建的凭证所需属性的信息。序列按优先顺序排列,从最优先到最不优先。客户端 会尽力创建它所能创建的最优先凭证。

PublicKeyCredentialCreationOptions/timeout

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS Safari13.3+Android 版 Chrome67+Android WebView三星 InternetOpera Mobile48+

timeout, 类型为 unsigned long

此成员指定调用者愿意等待调用完成的时间,以毫秒为单位。这被视为提示,可能会被 客户端 覆盖。

PublicKeyCredentialCreationOptions/excludeCredentials

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS Safari13.3+Android 版 Chrome67+Android WebView三星 InternetOpera Mobile48+

excludeCredentials, 类型为 sequence<PublicKeyCredentialDescriptor>,默认为 []

此成员供希望限制在单个验证器上为同一帐户创建多个凭证的 依赖方 使用。如果新凭证将在已包含此参数中列出的凭证之一的验证器上创建,客户端 被请求返回错误。

PublicKeyCredentialCreationOptions/authenticatorSelection

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS Safari13.3+Android 版 Chrome67+Android WebView三星 InternetOpera Mobile48+

authenticatorSelection, 类型为 AuthenticatorSelectionCriteria

此成员供希望选择适当验证器参与 create() 操作的 依赖方 使用。

PublicKeyCredentialCreationOptions/attestation

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Android 版 FirefoxiOS Safari13.3+Android 版 Chrome67+Android WebView三星 InternetOpera Mobile48+

attestation, 类型为 DOMString,默认为 "none"

此成员供希望表达其对 证明传输 的偏好的 依赖方 使用。其值应为 AttestationConveyancePreference 的成员。客户端平台 必须忽略未知值,将未知值视为 成员不存在。 其默认值为 "none"。

extensions, 类型为 AuthenticationExtensionsClientInputs

此成员包含请求客户端和验证器执行额外处理的附加参数。例如,调用者可以请求仅使用具有某些能力的验证器来创建凭证,或请求在 证明对象 中返回特定信息。一些扩展定义在 § 9 WebAuthn 扩展 中;有关最新注册 WebAuthn 扩展 的列表,请参阅由 [RFC8809] 建立的 IANA "WebAuthn 扩展标识符" 注册表 [IANA-WebAuthn-Registries]

5.4.1.公钥凭证实体描述(字典 PublicKeyCredentialEntity

PublicKeyCredentialEntity 字典描述了一个用户账户,或一个 WebAuthn 依赖方,该账户或依赖方与某个 公钥凭证 相关联,或者相应地,指向某个 作用域

dictionary PublicKeyCredentialEntity {
    required DOMString    name;
};
name 类型为 DOMString

实体的人类可读名称。其功能取决于PublicKeyCredentialEntity 所表示的内容:

  • 当被继承自 PublicKeyCredentialRpEntity 时,它是一个 人类可读 的标识符,用于 依赖方,仅供显示。例如,“ACME Corporation”、“Wonderful Widgets, Inc.” 或 “ОАО Примертех”。

  • 当被继承自 PublicKeyCredentialUserEntity 时,它是一个 人类可读 的标识符,用于用户帐户。它仅供显示,即帮助用户确定相似 displayName 的用户帐户之间的差异。例如,“alexm”、“alex.mueller@example.com” 或 “+14255551234”。

    • 依赖方 可能允许用户选择此值。 依赖方 应该执行强制措施,如在 [RFC8265] 第3.4.3节中规定的,对于PRECIS IdentifierClass 的用户名大小写保留配置文件 [RFC8264],在设置 name 的值或向用户显示该值时。

    • 该字符串可能包含语言和方向元数据。 依赖方 应该考虑提供此信息。有关如何编码这些元数据,请参见 § 6.4.2 语言和方向编码

    • 客户端应根据[RFC8265]第3.4.3节中关于PRECIS IdentifierClass的UsernameCasePreserved配置文件的规定,执行对name值的强制措施,方法是在向用户显示该值或将该值作为authenticatorMakeCredential操作的参数包含之前进行。

客户端客户端平台身份验证器显示name的 值时,他们应始终使用UI元素为显示的值提供清晰的边界,并且不允许溢出到其他元素[css-overflow-3]

身份验证器可以截断name 成员的值,使其适合64字节内,如果身份验证器存储该值。有关截断和其他考虑事项,请参见§ 6.4.1 字符串截断

5.4.2. 依赖方凭证生成参数 (字典 PublicKeyCredentialRpEntity)

字典 PublicKeyCredentialRpEntity 用于在创建新凭证时提供额外的 依赖方 属性。

dictionary PublicKeyCredentialRpEntity : PublicKeyCredentialEntity {
    DOMString      id;
};
id, 类型为 DOMString

用于设置 RP ID依赖方 实体的唯一标识符。

5.4.3. 用户帐户凭证生成参数 (字典 PublicKeyCredentialUserEntity)

字典 PublicKeyCredentialUserEntity 用于在创建新凭证时提供额外的用户帐户属性。

dictionary PublicKeyCredentialUserEntity : PublicKeyCredentialEntity {
    required BufferSource   id;
    required DOMString      displayName;
};
id, 类型为 BufferSource

用户帐户实体的 用户句柄用户句柄 是一个不透明的 字节序列,最大大小为 64 字节,且不打算显示给用户。

为了确保安全操作,身份验证和授权决策必须基于此 id 成员,而不是 displayNamename 成员。请参见 [RFC8266] 第 6.1 节。

用户句柄不得包含用户的个人身份信息,例如用户名或电子邮件地址;详情请参见 § 14.6.1 用户句柄内容用户句柄 不得为空,但可以为 null。

注意: 用户句柄 不应 在不同帐户之间保持常量值,即使是对于 不可发现的凭据,因为某些身份验证器始终创建 可发现的凭据。因此,常量的 用户句柄 将阻止用户在同一 依赖方 上使用此类身份验证器与多个帐户配合使用。

displayName, 类型为 DOMString

用户帐户的 易理解 名称,仅用于显示。例如,“Alex Müller” 或 “田中倫”。依赖方 应允许用户选择此名称,并且不应限制选择超过必要范围。

客户端客户端平台,或 验证器 显示 displayName 的值时,应该始终使用 UI 元素提供明确的边界,并且不要允许溢出到其他元素 [css-overflow-3]

验证器 必须接受并存储至少 64 字节长度的 displayName 成员值。验证器可以截断 displayName 成员值,使其适应 64 字节的长度。关于截断及其他注意事项的详细信息,请参阅 § 6.4.1 字符串截断

5.4.4. 认证器选择标准 (字典 AuthenticatorSelectionCriteria)

WebAuthn 依赖方 可以使用字典 AuthenticatorSelectionCriteria 指定他们对认证器属性的要求。

dictionary AuthenticatorSelectionCriteria {
    DOMString                    authenticatorAttachment;
    DOMString                    residentKey;
    boolean                      requireResidentKey = false;
    DOMString                    userVerification = "preferred";
};
authenticatorAttachment, 类型为 DOMString

如果此成员存在,符合条件的身份验证器将仅限于附加有指定的 § 5.4.5 身份验证器附加枚举 (enum AuthenticatorAttachment) 的身份验证器。该值应该是 AuthenticatorAttachment 的成员,但 客户端平台 必须忽略未知值,将未知值视为 成员不存在

residentKey, 类型为 DOMString

指定 依赖方 希望创建 客户端可发现的凭证 的程度。出于历史原因,命名保留了已弃用的“resident”术语。该值应该是 ResidentKeyRequirement 的成员,但 客户端平台 必须忽略未知值,将其视为 成员不存在。如果未给出任何值,则有效值为 required,如果 requireResidentKeytrue,或者如果它是 false 或缺失,则为 discouraged

请参见 ResidentKeyRequirement,了解 residentKey 的值和语义。

requireResidentKey, 类型为 boolean,默认为 false

此成员保留用于与 WebAuthn Level 1 的向后兼容性,并且出于历史原因,其命名保留了已弃用的“resident”术语,用于 可发现凭证依赖方 应仅在 residentKey 设置为 required 时,将其设置为 true

userVerification, 类型为 DOMString,默认为 "preferred"

此成员描述 依赖方用户验证 的要求,适用于 create() 操作。符合条件的身份验证器将仅限于能够满足此要求的身份验证器。该值应为 UserVerificationRequirement 的成员,但 客户端平台 必须忽略未知值,将其视为 成员不存在

5.4.5. 认证器附件枚举 (枚举 AuthenticatorAttachment)

此枚举的值描述了认证器附件模式依赖方在调用navigator.credentials.create()创建凭证时,使用它来表示首选的认证器附件模式

enum AuthenticatorAttachment {
    "platform",
    "cross-platform"
};

注意: AuthenticatorAttachment 枚举被故意忽略引用,请参见 § 2.1.1 枚举作为 DOMString 类型

platform

此值表示平台附件

cross-platform

此值表示跨平台附件

注意: 认证器附件模式选择选项仅在[[Create]](origin, options, sameOriginWithAncestors)操作中可用。依赖方可以使用该选项,例如,确保用户拥有一个用于在其他客户端设备上进行身份验证的漫游凭证;或专门注册一个平台凭证,以便使用特定的客户端设备更轻松地重新身份验证。[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)操作没有认证器附件模式选择选项,因此依赖方应接受用户的任意已注册凭证。然后,客户端和用户将使用当时可用且便捷的任何凭证。

5.4.6. 常驻密钥要求枚举 (枚举 ResidentKeyRequirement)

enum ResidentKeyRequirement {
    "discouraged",
    "preferred",
    "required"
};

注意: ResidentKeyRequirement 枚举被故意忽略引用,请参见 § 2.1.1 枚举作为 DOMString 类型

此枚举的值描述了依赖方对于客户端可发现的凭证(以前称为常驻凭证常驻密钥)的要求:

discouraged

此值表示依赖方更倾向于创建服务器端凭证,但会接受客户端可发现的凭证

注意: 依赖方不能要求创建的凭证必须是服务器端凭证,而凭证属性扩展可能不会返回rk属性的值。因此,依赖方可能无法知道凭证是否为服务器端凭证,也无法知道是否创建了具有相同用户句柄的第二个凭证会将第一个凭证移除。

preferred

此值表示依赖方强烈倾向于创建客户端可发现的凭证,但会接受服务器端凭证。例如,如果需要创建客户端可发现的凭证,用户代理应引导用户设置用户验证。在这种情况下,这优先于userVerification的设置。

required

此值表示依赖方要求创建一个客户端可发现的凭证,并且如果无法创建客户端可发现的凭证,则会接受错误。

注意: 依赖方 可以通过检查 凭证属性扩展 的返回值,结合 options.authenticatorSelection.residentKey 提供的值,来获取关于身份验证器是否创建了 客户端可发现的凭证 的信息。 这在使用 不推荐推荐 作为 options.authenticatorSelection.residentKey 时很有用, 因为在这些情况下,身份验证器 可能会创建 任意 一种 客户端可发现的凭证服务器端凭证

5.4.7. 证明传递偏好枚举 (枚举 AttestationConveyancePreference)

WebAuthn 依赖方可以使用AttestationConveyancePreference来指定其在凭证生成过程中关于证明传递的偏好。

enum AttestationConveyancePreference {
    "none",
    "indirect",
    "direct",
    "enterprise"
};

注意: AttestationConveyancePreference 枚举被故意忽略引用,请参见 § 2.1.1 枚举作为 DOMString 类型

none

此值表示 依赖方认证器 证明 不感兴趣。例如,为了 潜在避免获取 用户同意 将识别信息传递给 依赖方,或节省一次 与 证明CA匿名化CA 的往返。

这是默认值。

indirect

此值表示 依赖方 偏好通过传递可验证的 证明 来获取 证明声明,但允许客户端决定如何获取这些 证明声明。 客户端可以将认证器生成的 证明声明 替换为由 证明声明,由 匿名化CA 生成,以保护用户隐私,或帮助 依赖方 在异构生态系统中进行证明验证。

注意: 在这种情况下,不能保证 依赖方 会获得可验证的 证明声明。例如,在认证器使用 自我证明 的情况下。

direct

此值表示 依赖方 希望接收由 认证器 生成的 证明声明

enterprise

此值表示 依赖方 希望接收可能包含唯一标识信息的 证明声明。 这适用于企业内部的受控部署,其中组织希望将注册与特定认证器绑定。除非用户代理或认证器配置允许为请求的 RP ID 提供此类证明,否则用户代理不得提供此类证明。

如果允许,用户代理应在 调用时 向认证器发出请求企业证明的信号,并将生成的 AAGUID证明声明 不做更改地传递给 依赖方

5.5. 断言生成选项 (字典 PublicKeyCredentialRequestOptions)

PublicKeyCredentialRequestOptions

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Firefox for Android?iOS Safari13.3+Chrome for Android67+Android WebView67+三星 InternetOpera Mobile48+

PublicKeyCredentialRequestOptions 字典为get()提供生成断言所需的数据。其challenge成员必须存在,而其他成员是可选的。

dictionary PublicKeyCredentialRequestOptions {
    required BufferSource                challenge;
    unsigned long                        timeout;
    USVString                            rpId;
    sequence<PublicKeyCredentialDescriptor> allowCredentials = [];
    DOMString                            userVerification = "preferred";
    AuthenticationExtensionsClientInputs extensions;
};

PublicKeyCredentialRequestOptions/challenge

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Firefox for Android?iOS Safari13.3+Chrome for Android67+Android WebView67+三星 InternetOpera Mobile48+

challenge, 类型 BufferSource

此成员表示选定的认证器在生成 身份验证断言时签名的挑战及其他数据。请参见 § 13.4.3 加密挑战 的安全考量。

PublicKeyCredentialRequestOptions/timeout

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Firefox for Android?iOS Safari13.3+Chrome for Android67+Android WebView67+三星 InternetOpera Mobile48+

timeout, 类型 unsigned long

此可选成员指定调用完成所愿等待的时间(以毫秒为单位)。该值被视为提示,且可能会被客户端覆盖。

PublicKeyCredentialRequestOptions/rpId

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Firefox for Android?iOS Safari13.3+Chrome for Android67+Android WebView67+三星 InternetOpera Mobile48+

rpId, 类型 USVString

此可选成员指定调用方声称的依赖方标识符。如果省略,其值将为CredentialsContainer 对象的相关设置对象来源有效域

PublicKeyCredentialRequestOptions/allowCredentials

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Firefox for Android?iOS Safari13.3+Chrome for Android67+Android WebView67+三星 InternetOpera Mobile48+

allowCredentials, 类型 sequence<PublicKeyCredentialDescriptor>, 默认值为 []

此可选成员包含公钥凭证PublicKeyCredentialDescriptor 对象列表,按调用者的偏好顺序排列(列表中的第一个项目是最偏好的凭据,依此类推)。

PublicKeyCredentialRequestOptions/userVerification

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Firefox for Android?iOS Safari13.3+Chrome for Android67+Android WebView67+三星 InternetOpera Mobile48+

userVerification, 类型 DOMString, 默认值为 "preferred"

此可选成员描述依赖方用户验证的要求, 用于 get() 操作。该值应为UserVerificationRequirement的成员, 但客户端平台必须忽略未知值,将未知值视为该成员不存在。只会过滤符合该要求的认证器。

PublicKeyCredentialCreationOptions/extensions

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Firefox for Android?iOS Safari13.3+Chrome for Android67+Android WebView67+三星 InternetOpera Mobile48+

PublicKeyCredentialRequestOptions/extensions

在所有当前引擎中。

Firefox60+Safari13+Chrome67+
Opera54+Edge79+
Edge (旧版)IE
Firefox for Android?iOS Safari13.3+Chrome for Android67+Android WebView67+三星 InternetOpera Mobile48+

extensions, 类型 AuthenticationExtensionsClientInputs

此可选成员包含请求客户端和认证器进行额外处理的额外参数。例如,如果需要从用户那里获得交易确认,则提示字符串可能包含在扩展中。

5.6. 使用 AbortSignal 中止操作

鼓励开发者利用 AbortController 来管理 [[Create]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 操作。 详细说明请参见 DOM §3.3 使用 AbortController 和 AbortSignal 对象在API中部分。

注意: DOM §3.3 使用 AbortController 和 AbortSignal 对象在API中部分规定,集成了 AbortController 的 Web 平台 API 一旦设置了中止标志,必须立即拒绝 Promise。 鉴于 [[Create]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 方法复杂的继承和并行结构,这两个 API 的算法通过在三个地方检查中止标志来满足此要求。在 [[Create]](origin, options, sameOriginWithAncestors) 的情况下,首先在 Credential Management 1 §2.5.4 创建凭证中,紧接在调用 [[Create]](origin, options, sameOriginWithAncestors) 之前检查中止标志,然后在 § 5.1.3 创建新凭证 - PublicKeyCredential 的 [[Create]](origin, options, sameOriginWithAncestors) 方法中,在 认证器会话开始前检查, 最后在 认证器会话期间检查。对于 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 方法来说,也是如此。

可见性焦点状态决定了窗口对象是否应该继续 [[Create]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 操作。当与该窗口对象关联的[文档]失去焦点时, [[Create]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 操作应被中止。

WHATWG HTML 工作组正在讨论是否在浏览上下文获得或失去焦点时提供一个钩子。 如果提供了钩子,上述段落将会被更新以包括该钩子。 更多详情参见 WHATWG HTML 工作组问题 #2711

5.7. WebAuthn 扩展输入和输出

下面的小节定义了用于传递 WebAuthn 扩展输入和输出的数据类型。

注意:认证器扩展输出作为认证器数据的一部分传递 (参见表 1)。

注意:下面定义的类型——AuthenticationExtensionsClientInputsAuthenticationExtensionsClientOutputs—— 适用于 注册扩展认证扩展。 其名称中的“Authentication...”部分应理解为“WebAuthentication...”

5.7.1. 认证扩展客户端输入(字典 AuthenticationExtensionsClientInputs

dictionary AuthenticationExtensionsClientInputs {
};

这是一个包含零个或多个客户端扩展输入值的字典,用于 WebAuthn 扩展

5.7.2. 认证扩展客户端输出(字典 AuthenticationExtensionsClientOutputs

dictionary AuthenticationExtensionsClientOutputs {
};

这是一个包含零个或多个客户端扩展输出值的字典,用于 WebAuthn 扩展

5.7.3. 认证扩展认证器输入 (CDDL 类型 AuthenticationExtensionsAuthenticatorInputs

AuthenticationExtensionsAuthenticatorInputs = {
  * $$extensionInput .within ( tstr => any )
}

CDDL 类型 AuthenticationExtensionsAuthenticatorInputs定义了一个 CBOR 映射 ,包含零个或多个认证器扩展输入值,用于 WebAuthn 扩展。 扩展可以按§ 9.3 扩展请求参数中描述添加成员。

此类型不会暴露给依赖方,但会被客户端认证器使用。

5.7.4. 认证扩展认证器输出 (CDDL 类型 AuthenticationExtensionsAuthenticatorOutputs

AuthenticationExtensionsAuthenticatorOutputs = {
  * $$extensionOutput .within ( tstr => any )
}

CDDL 类型 AuthenticationExtensionsAuthenticatorOutputs定义了一个 CBOR 映射 ,包含零个或多个认证器扩展输出值,用于 WebAuthn 扩展。 扩展可以按§ 9.3 扩展请求参数中描述添加成员。

5.8. 支持的数据结构

公钥凭证类型使用某些在支持规范中定义的数据结构。如下所示。

5.8.1. WebAuthn 签名中使用的客户端数据(字典 CollectedClientData

客户端数据表示 WebAuthn 依赖方客户端的上下文绑定。这是一个键值对映射,其中键为字符串。值可以是任何在 JSON 中有有效编码的类型。其结构由以下 Web IDL 定义。

注意: CollectedClientData 可能在未来扩展。因此在解析时必须容忍未知的键和任何键的重新排序。另见§ 5.8.1.2 限制性验证算法

dictionary CollectedClientData {
            required DOMString           type;
            required DOMString           challenge;
            required DOMString           origin;
            boolean                      crossOrigin;
            TokenBinding                 tokenBinding;
        };
        
        dictionary TokenBinding {
            required DOMString status;
            DOMString id;
        };
        
        enum TokenBindingStatus { "present", "supported" };
        
type, 类型 DOMString

当创建新凭证时,此成员包含字符串"webauthn.create",当从现有凭证获取断言时,包含字符串"webauthn.get"。此成员的目的是防止某些类型的签名混淆攻击(攻击者将一个合法签名替换为另一个)。

challenge, 类型 DOMString

此成员包含依赖方提供的挑战的 base64url 编码。见§ 13.4.3 加密挑战安全注意事项。

origin, 类型 DOMString

此成员包含请求者的完全限定的来源,由客户端提供给认证器,格式为[RFC6454]定义的语法。

crossOrigin, 类型 boolean

此成员包含传递给内部方法sameOriginWithAncestors参数值的反值。

tokenBinding, 类型 TokenBinding

此可选成员包含关于与依赖方通信时使用的令牌绑定协议[TokenBinding]状态的信息。它的缺失表示客户端不支持令牌绑定。

status, 类型 DOMString

此成员应该是TokenBindingStatus的成员,但客户端平台必须忽略未知的值,将未知的值视为tokenBinding 成员不存在。已知时,此成员是以下之一:

supported

表示客户端支持令牌绑定,但在与依赖方通信时未协商使用。

present

表示在与依赖方通信时使用了令牌绑定。在这种情况下,必须存在id成员。

注意: TokenBindingStatus枚举故意不被引用,见§ 2.1.1 枚举作为 DOMString 类型

id, 类型 DOMString

如果statuspresent,则此成员必须存在,并且必须是使用与依赖方通信时使用的令牌绑定 IDbase64url 编码

注意:获取令牌绑定 ID客户端平台的特定操作。

客户端使用CollectedClientData结构来计算以下数量:

客户端数据的 JSON 兼容序列化

这是对CollectedClientData字典执行JSON 兼容序列化算法的结果。

序列化客户端数据的哈希值

这是客户端构造的客户端数据 JSON 兼容序列化的哈希值(使用 SHA-256 计算)。

5.8.1.1. 序列化

CollectedClientData的序列化是JSON 序列化为字节算法的一个子集。也就是说,它生成了CollectedClientData的有效 JSON 编码,但也提供了额外的结构,验证器可以利用这些结构来避免集成完整的 JSON 解析器。虽然建议验证器执行标准的 JSON 解析,但在完整 JSON 解析器体积过大的情况下,它们可以在上下文中使用以下更有限的算法。此验证算法只需要base64url 编码、字节串的追加(可以通过在固定模板中写入实现)以及三个条件检查(假设输入已知不需要转义)。

序列化算法通过将连续的字节串追加到最初为空的部分结果中,直到获得完整的结果。

  1. result为空字节串。

  2. 将0x7b2274797065223a({"type":)追加到result

  3. CCDToString(type)追加到result

  4. 将0x2c226368616c6c656e6765223a(,"challenge":)追加到result

  5. CCDToString(challenge)追加到result

  6. 将0x2c226f726967696e223a(,"origin":)追加到result

  7. CCDToString(origin)追加到result

  8. 将0x2c2263726f73734f726967696e223a(,"crossOrigin":)追加到result

  9. 如果crossOrigin不存在或为false

    1. 将0x66616c7365(false)追加到result

  10. 否则:

    1. 将0x74727565(true)追加到result

  11. 创建CollectedClientData的临时副本,并删除字段typechallengeorigincrossOrigin(如果存在)。

  12. 如果临时副本中没有剩余字段:

    1. 将0x7d(})追加到result

  13. 否则:

    1. 调用将 JSON 序列化为字节,在临时副本上产生字节串remainder

    2. 将0x2c(,)追加到result

    3. 移除remainder的前导字节。

    4. remainder追加到result

  14. 序列化的结果是result的值。

在上述算法中使用的函数CCDToString定义如下:

  1. encoded为空字节串。

  2. 将0x22(")追加到encoded

  3. 调用ToString将给定对象转换为字符串。

  4. 对于结果字符串中的每个代码点,如果代码点:

    属于集合 {U+0020, U+0021, U+0023–U+005B, U+005D–U+10FFFF}

    将该代码点的 UTF-8 编码追加到encoded

    是 U+0022

    将0x5c22(\")追加到encoded

    是 U+005C

    将0x5c5c(\\)追加到encoded

    否则

    将0x5c75(\u)追加到encoded,然后追加四个小写的十六进制数字,这些数字表示该代码点的基数为16的数字。

  5. 将0x22(")追加到encoded

  6. 该函数的结果是encoded的值。

5.8.1.2. 有限验证算法

如果验证器无法支持完整的 JSON 解析器,可以使用以下算法来验证编码的CollectedClientData

  1. 该算法的输入包括:

    1. 一个字节串clientDataJSON,其中包含clientDataJSON——要验证的序列化的CollectedClientData

    2. 一个字符串type,其中包含预期的type

    3. 一个字节串challenge,其中包含在PublicKeyCredentialRequestOptionsPublicKeyCredentialCreationOptions中提供的挑战字节串。

    4. 一个字符串origin,其中包含向用户代理发出请求的预期origin

    5. 一个布尔值crossOrigin,当且仅当请求应在跨源iframe内执行时,该值为true。

  2. expected为空字节串。

  3. 将0x7b2274797065223a({"type":)追加到expected

  4. CCDToString(type)追加到expected

  5. 将0x2c226368616c6c656e6765223a(,"challenge":)追加到expected

  6. challenge执行base64url 编码,生成字符串challengeBase64

  7. CCDToString(challengeBase64)追加到expected

  8. 将0x2c226f726967696e223a(,"origin":)追加到expected

  9. CCDToString(origin)追加到expected

  10. 将0x2c2263726f73734f726967696e223a(,"crossOrigin":)追加到expected

  11. 如果crossOrigin为true:

    1. 将0x74727565(true)追加到expected

  12. 否则,即crossOrigin为false:

    1. 将0x66616c7365(false)追加到expected

  13. 如果expected不是clientDataJSON的前缀,则验证失败。

  14. 如果clientDataJSON长度不比expected长至少一个字节,则验证失败。

  15. 如果clientDataJSON在与expected长度相等的偏移处的字节:

    是0x7d

    验证成功。

    是0x2c

    验证成功。

    否则

    验证失败。

5.8.1.3. 未来开发

为了与有限验证算法保持兼容,未来版本的规范不得删除typechallengeorigincrossOrigin字段从CollectedClientData中。 规范也不得更改序列化算法中这些字段的序列化顺序。

如果向CollectedClientData中添加额外字段,那么采用有限验证算法的验证器将无法在上面两个算法更新以包含这些字段之前考虑这些字段。 一旦发生此类更新,添加的字段将继承前段所述的相同限制。这类算法更新必须适应由以前版本生成的序列化数据。 也就是说,验证算法必须处理第五个键值对在由使用先前版本的用户代理生成时可能不会出现在第五位(或者根本不存在)的情况。

5.8.2. 凭证类型枚举 (枚举 PublicKeyCredentialType)

enum PublicKeyCredentialType {
    "public-key"
};

注意: PublicKeyCredentialType 枚举特意未被引用,详见§ 2.1.1 枚举作为 DOMString 类型

此枚举定义了有效的凭证类型。它是一个扩展点;随着更多凭证类型的定义,未来可以向其添加值。根据认证器的类型,使用此枚举的值对身份验证断言和认证结构进行版本控制。

当前定义了一个凭证类型,即“public-key”。

5.8.3. 凭证描述符 (字典 PublicKeyCredentialDescriptor)

dictionary PublicKeyCredentialDescriptor {
    required DOMString                    type;
    required BufferSource                 id;
    sequence<DOMString>                   transports;
};

这个字典包含了调用者在将公钥凭证作为输入参数传递给 create()get() 方法时指定的属性。它与通过这些方法返回的 PublicKeyCredential 对象的字段相对应。

type, 类型为 DOMString

此成员包含调用者引用的公钥凭证的类型。该值应为PublicKeyCredentialType的成员,但客户端平台必须忽略任何具有未知类型PublicKeyCredentialDescriptor

id, 类型为 BufferSource

此成员包含调用者引用的公钥凭证凭证ID

transports, 类型为 sequence<DOMString>

此可选成员包含指示客户端如何与调用者引用的公钥凭证管理认证器通信的提示。该值应为AuthenticatorTransport的成员,但客户端平台必须忽略未知值。

getTransports()操作可以为此成员提供适当的值。 在注册新凭证时,依赖方应存储getTransports()返回的值。 当为该凭证创建PublicKeyCredentialDescriptor时, 依赖方应检索该存储的值并将其设置为transports成员的值。

5.8.4. 认证器传输枚举 (枚举 AuthenticatorTransport)

enum AuthenticatorTransport {
    "usb",
    "nfc",
    "ble",
    "internal"
};

注意: 枚举 AuthenticatorTransport 故意不被引用,请参见 § 2.1.1 作为 DOMString 类型的枚举

身份验证器 可以实现各种 传输方式客户端 进行通信。这个枚举定义了关于客户端如何与特定身份验证器通信以获取特定凭证的断言的提示。请注意,这些提示表示 WebAuthn 依赖方 对身份验证器如何被访问的最佳推测。一个 依赖方 通常会通过 公钥凭证 了解到支持的传输方式,方法是通过 getTransports()
usb

表示相应的 身份验证器 可以通过可移动USB连接。

nfc

表示相应的 身份验证器 可以通过近场通信 (NFC) 连接。

ble

表示相应的 身份验证器 可以通过蓝牙智能 (蓝牙低能耗 / BLE) 连接。

internal

表示相应的 身份验证器 是通过特定于 客户端设备 的传输方式进行连接的,即它是一个 平台身份验证器。这些身份验证器不能从 客户端设备 中移除。

5.8.5. 加密算法标识符 (typedef COSEAlgorithmIdentifier)

typedef long COSEAlgorithmIdentifier;
COSEAlgorithmIdentifier的 值是一个用于标识加密算法的数字。 算法标识符应为 IANA COSE 算法注册表中注册的值 [IANA-COSE-ALGS-REG], 例如,"ES256" 对应的代码为-7,"RS256" 对应的代码为 -257

COSE 算法注册表允许在 COSE 密钥中由其他参数指定的自由度。为了促进互操作性,本规范对凭证公钥做出以下额外保证:

  1. 使用算法 ES256 (-7) 的密钥必须将 P-256 (1) 指定为 crv 参数,且不得使用压缩点形式。

  2. 使用算法 ES384 (-35) 的密钥必须将 P-384 (2) 指定为 crv 参数,且不得使用压缩点形式。

  3. 使用算法 ES512 (-36) 的密钥必须将 P-521 (3) 指定为 crv 参数,且不得使用压缩点形式。

  4. 使用算法 EdDSA (-8) 的密钥必须将 Ed25519 (6) 指定为 crv 参数。(这些在 COSE 中总是使用压缩形式。)

注意: 使用这些算法正确实现签名验证需要进行许多检查。其中之一是,在处理未压缩的椭圆曲线点时,实施应检查点是否实际上在曲线上。特别强调此检查,因为它被认为是最有可能在加密库与其他代码之间被忽略的地方。

5.8.6. 用户验证要求枚举 (枚举 UserVerificationRequirement)

enum UserVerificationRequirement {
    "required",
    "preferred",
    "discouraged"
};

WebAuthn 依赖方 可能会要求在某些操作中进行用户验证,而在其他操作中则不需要,并且可以使用此类型来表达其需求。

注意: 枚举UserVerificationRequirement 故意不被引用,请参见 § 2.1.1 作为 DOMString 类型的枚举

required

此值表示依赖方要求在操作中进行用户验证,如果响应中未设置UV 标志,则操作将失败。

preferred

此值表示依赖方更喜欢在操作中进行用户验证,但如果响应中未设置UV 标志,操作也不会失败。

discouraged

此值表示依赖方不希望在操作中使用用户验证(例如,为了尽量减少对用户交互流程的干扰)。

5.9. 权限策略集成

Headers/Feature-Policy/publickey-credentials-get

仅在一个当前引擎中可用。

FirefoxSafariChrome84+
OperaEdge84+
Edge (旧版)IE
Firefox for AndroidiOS SafariChrome for Android84+Android WebView84+Samsung InternetOpera Mobile

本规范定义了一个由 特征标识符令牌"publickey-credentials-get" 识别的策略控制特征。 它的默认允许列表为 'self'。[Permissions-Policy]

一个文档权限策略决定了该文档中的任何内容是否 允许成功调用Web 认证 API, 即通过navigator.credentials.get({publicKey:..., ...})。 如果在任何文档中禁用了此功能,则该文档中的所有内容都将无法使用上述方法:尝试这样做将返回错误

注意:[CREDENTIAL-MANAGEMENT-1]中指定的算法执行实际的权限策略评估。这是因为当需要访问当前设置对象时,需要进行此类策略评估。[[Create]](origin, options, sameOriginWithAncestors)[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 内部方法没有这样的访问权限,因为它们是 并行调用的(通过 [CREDENTIAL-MANAGEMENT-1]中指定的算法)。

5.10. iframe元素中使用 Web 认证

Web 身份验证 API 默认在跨源的 iframe 中被禁用。 要覆盖此默认策略,并指示允许跨源 iframe 调用 Web 身份验证 API[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 方法,请在 iframe 元素上指定 iframe 元素,并在 publickey-credentials-get 特性标识符令牌的值中包含在 allow 属性的值中。

依赖方 在嵌入式上下文中使用 WebAuthn API 时,应查看 § 13.4.2 嵌入式使用的可见性考虑, 以了解 UI 重绘 及其可能的缓解措施。

6. WebAuthn 认证器模型

Web认证API隐含了WebAuthn认证器的具体抽象功能模型。本节描述该认证器模型

客户端平台可以以任何所需方式实现和展示此抽象模型。但是,当客户端Web认证API实现对该客户端平台支持的认证器进行操作时,其行为必须与§ 5 Web认证API中指定的行为无区别。

注意:[FIDO-CTAP]是此模型的一个具体实现示例,但它返回的数据与WebAuthn API算法期望的数据有所不同。CTAP2响应消息是使用整数键构造的CBOR映射,而不是在本规范中为相同对象定义的字符串键。客户端需要对这些数据进行必要的转换。[FIDO-CTAP]规范在第§6.2. 响应节中详细说明了CTAP2整数键与WebAuthn字符串键之间的映射。

对于认证器,该模型定义了它们必须支持的逻辑操作以及它们向客户端和WebAuthn依赖方公开的数据格式。然而,除非它们对于与依赖方的互操作性是必需的,否则它不定义认证器如何与客户端设备通信的细节。例如,此抽象模型不定义通过USB或NFC等传输方式连接认证器到客户端的协议。同样,此抽象模型也不定义特定的错误代码或返回它们的方法;然而,它确实根据客户端的需求定义了错误行为。因此,提到特定错误代码是为了说明哪些错误条件必须能够相互区分(或不区分)以实现符合且安全的客户端实现。

依赖方可以在认为必要时通过在创建凭证和/或生成断言时规定各种认证器特征,通过使用凭证创建选项断言生成选项分别影响认证器选择。WebAuthn API背后的算法整理这些选项并将它们传递给以下定义的适用认证器操作

在此抽象模型中,认证器提供密钥管理和加密签名。它可以嵌入在WebAuthn客户端中或完全放置在单独的设备中。认证器本身可以包含一个以高于认证器其余部分的安全级别运行的加密模块。对于嵌入在WebAuthn客户端中的认证器,这一点尤为重要,因为在这些情况下,此加密模块(例如,可能是TPM)可以被视为比认证器的其余部分更值得信赖。

每个认证器存储一个凭证映射,这是从(rpId,[userHandle])到公钥凭证源映射

此外,每个认证器具有一个AAGUID,这是一个128位标识符,用于指示认证器的类型(例如,品牌和型号)。AAGUID必须由制造商选择,在该制造商生产的所有实质上相同的认证器中保持一致,并且与其他类型认证器的AAGUID不同(高概率)。应随机生成给定类型的认证器的AAGUID以确保这一点。依赖方可以使用AAGUID根据其他来源的信息推断认证器的某些属性,例如认证级别和密钥保护的强度。

认证器的主要功能是提供绑定到各种上下文数据的WebAuthn签名。这些数据在从服务器到认证器的签名请求过程中被观察并添加到堆栈的不同级别。服务器在验证签名时会检查这些绑定是否符合预期值。这些上下文绑定分为两部分:由依赖方或客户端添加的,称为客户端数据;以及由认证器添加的,称为认证器数据。认证器对客户端数据进行签名,但对其内容不感兴趣。为了节省带宽和认证器的处理需求,客户端对客户端数据进行哈希处理,并仅将结果发送给认证器。认证器对序列化客户端数据的哈希与其自己的认证器数据组合进行签名。

此设计的目标可总结如下。

认证器生成加密签名的目的是双重的:

  1. 当通过 authenticatorMakeCredential 操作创建一个新的 公钥凭证 时,会生成一个 认证签名认证签名 提供了有关 认证器 和凭证的某些属性的加密证明。例如,认证签名 断言了 认证器 的类型(通过其 AAGUID 表示)和 凭证公钥认证签名认证私钥 签名,具体的私钥选择取决于所需的 认证 类型。 有关 认证 的更多详情,请参见 § 6.5 认证

  2. 当调用authenticatorGetAssertion方法时,会生成一个断言签名。它表示认证器的断言,即用户已同意特定交易,例如登录或完成购买。因此,断言签名断言拥有特定凭证私钥认证器已尽最大努力确定请求此交易的用户与同意创建该特定公钥凭证的用户为同一人。它还断言了称为客户端数据的附加信息,这些信息可能对调用者有用,例如提供用户同意的方式,以及认证器向用户显示的提示。断言签名的格式如下方图4所示。

WebAuthn签名一词指认证签名断言签名。这些签名的格式以及生成它们的过程在下面规定。

6.1. 认证器数据

认证器数据结构编码了由认证器生成的上下文绑定。这些绑定由认证器本身控制,并从WebAuthn 依赖方对认证器安全属性的评估中获得信任。在一种极端情况下,认证器可能嵌入在客户端中,其绑定的可信度可能不会超过客户端数据。在另一种极端情况下,认证器可能是具有高安全硬件和软件的独立实体,通过安全通道连接到客户端。在这两种情况下,依赖方以相同的格式接收认证器数据,并根据对认证器的了解做出信任决策。

认证器数据具有紧凑但可扩展的编码。这是期望的,因为认证器可能是具有有限能力和低功耗需求的设备,其软件栈远比客户端平台简单得多。

认证器数据结构是一个37字节或更多的字节数组,如所示。

名称 长度(字节) 描述
rpIdHash 32 SHA-256哈希值,表示 RP ID 该凭证被 凭证 作用域
flags 1 标志位(位0是最低有效位):
signCount 4 签名计数器,32位无符号大端整数。
attestedCredentialData 可变(如果存在) 已认证凭证数据(如果存在)。有关详细信息,请参阅 § 6.5.1 已认证凭证数据。其长度取决于 凭证ID的长度以及 凭证ID凭证公钥 的认证。
extensions 可变(如果存在) 扩展定义的 身份验证器数据。这是一个 CBOR [RFC8949] 映射,具有 扩展标识符 作为键, 以及 身份验证器扩展输出 作为值。详情请见 § 9 WebAuthn 扩展
认证器数据布局。名称列中的名称仅供本文档内引用,并不在实际的认证器数据表示中出现。

RP ID最初是在创建凭证时从客户端接收到的,并在生成断言时再次接收。然而,它在一些重要方面不同于其他客户端数据。首先,与客户端数据不同,凭证的RP ID在操作之间不会改变,而是在该凭证的整个生命周期内保持不变。其次,在authenticatorGetAssertion操作期间,认证器通过验证请求的公共密钥凭证RP ID客户端提供的RP ID完全匹配来验证它,并确保其符合该凭证的作用域

身份验证器 执行以下步骤生成 身份验证器数据 结构

展示了认证器数据结构的视觉表示。

认证器数据布局。
注意: 认证器数据描述了它自己的长度:如果AT和ED 标志未设置,则它的长度总是37字节。 认证凭证数据(仅在AT 标志设置时存在)描述了它自己的长度。如果ED 标志设置了,那么总长度为37字节加上认证凭证数据的长度(如果设置了AT 标志),再加上扩展输出的长度(一个CBOR映射)紧随其后。

确定认证凭证数据的长度是可变的,涉及确定凭证公钥的起始位置,取决于前面的凭证ID长度,然后确定凭证公钥的长度(参见RFC8152第7节)。

6.1.1. 签名计数器注意事项

身份验证器应实现 签名计数器 功能。这些计数器概念上是由身份验证器为每个凭证存储的,或者是作为整个身份验证器的全局计数器。凭证的初始 签名计数器 值在 signCount 中指定,该值来自 身份验证器数据,由 authenticatorMakeCredential 返回。每成功执行一次 authenticatorGetAssertion 操作,签名计数器都会增加一个正值,并且后续的值会再次通过 WebAuthn 依赖方身份验证器数据 中返回。签名计数器的目的是帮助 依赖方 检测克隆的身份验证器。克隆检测对于保护措施有限的身份验证器尤为重要。

一个 依赖方 存储最近一次 authenticatorGetAssertion 操作的 签名计数器。 (如果凭证上从未执行过 authenticatorGetAssertion 操作,则使用来自 authenticatorMakeCredential 操作的计数器。)在后续的 authenticatorGetAssertion 操作中,依赖方 将存储的 签名计数器 值与新的 signCount 值进行比较,该值从断言的 身份验证器数据 中返回。如果其中任何一个非零,并且新的 signCount 值小于或等于存储的值,则可能存在克隆的身份验证器,或者身份验证器可能出现故障。

检测到 签名计数器 不匹配并不能表明当前操作是由克隆的身份验证器还是原始身份验证器执行的。依赖方 应根据其具体情况适当处理这种情况,即根据其风险容忍度来处理。

身份验证器:

6.1.2. FIDO U2F Signature Format Compatibility

用于签署 断言签名 的格式,这些签名覆盖了 身份验证器数据 结构和 序列化客户端数据的哈希,与 FIDO U2F 身份验证签名格式兼容(请参见 第 5.4 节,来自 [FIDO-U2F-Message-Formats])。

这是因为 FIDO U2F 身份验证响应消息中签名数据的前 37 字节构成了一个有效的 身份验证器数据 结构,剩余的 32 字节是 序列化客户端数据的哈希。在这个 身份验证器数据 结构中,rpIdHash 是 FIDO U2F 应用程序参数,除了 UP 外,所有 标志 总是为零,并且 认证凭证数据扩展 永远不会存在。因此,FIDO U2F 身份验证签名可以通过与其他 断言签名 相同的程序进行验证,这些断言签名是由 authenticatorMakeCredential 操作生成的。

6.2. 认证器分类

许多使用案例取决于所使用的认证器的功能。 本节定义了这些功能的一些术语、它们的重要组合及其启用的使用案例。

例如:

上述示例说明了主要的 身份验证器类型 特征:

这些特性是独立的,理论上可以以任何方式组合,但表格 列出了和命名了某些特别关注的身份验证器类型

认证器类型 认证器附着方式 凭证存储方式 认证因素能力
第二因素平台认证器 平台 任何 单因素能力
用户验证平台认证器 平台 任何 多因素能力
第二因素漫游认证器 跨平台 服务器端存储 单因素能力
第一因素漫游认证器 跨平台 客户端存储 多因素能力
一些认证器类型的名称定义。

第二因素平台认证器(second-factor platform authenticator)在同一 客户端设备上进行重新认证时非常方便, 并且可以在启动新会话或恢复现有会话时添加额外的安全层。 第二因素漫游认证器(second-factor roaming authenticator)更可能 被用来在特定的 客户端设备 上进行首次认证, 或在多个用户共享的 客户端设备 上进行认证。

用户验证平台认证器第一因素漫游认证器 支持无密码的 多因素 认证。 除了凭证私钥(credential private key)的拥有证明外, 这些认证器还支持 用户验证,作为第二种 认证因素, 通常是 PIN 或 生物识别。 因此,认证器 可以充当两种类型的 认证因素, 从而启用 多因素 认证,同时消除了与 依赖方 共享密码的需求。

表格 中未命名的四种组合具有较少的明显使用案例:

以下小节更深入地定义了认证器附着模式凭证存储模式身份验证因素能力的各个方面。

6.2.1. 认证器附着模式

客户端可以通过多种机制与认证器通信。例如,客户端可以使用客户端设备特定的API与物理绑定到客户端设备认证器通信。另一方面,客户端可以使用各种标准化的跨平台传输协议(例如蓝牙,参见§ 5.8.4 认证器传输枚举 (enum AuthenticatorTransport))来发现和通信与跨平台附着认证器。我们将作为客户端设备一部分的认证器称为平台认证器,而那些通过跨平台传输协议可访问的则称为漫游认证器

某些 平台身份验证器 可能也可以根据上下文充当 漫游身份验证器。例如,一个集成在移动设备中的 平台身份验证器 可以通过蓝牙作为 漫游身份验证器 提供服务。在这种情况下,运行在移动设备上的 客户端 将识别该身份验证器为 平台身份验证器,而运行在其他 客户端设备 上并通过蓝牙与同一身份验证器通信的 客户端 将识别它为 漫游身份验证器

对于 平台身份验证器 的主要使用案例是将特定的 客户端设备 注册为“受信任的设备”,使得 客户端设备 本身充当未来 身份验证你所拥有的东西 认证因素。这样,用户将受益于无需为未来的 身份验证仪式 准备 漫游身份验证器,例如,用户不需要在口袋里翻找钥匙扣或手机。

使用漫游认证器的用例包括:在新客户端设备上首次进行认证,在很少使用的客户端设备上,多个用户共享的客户端设备,或者不包含平台认证器客户端设备;以及当政策或偏好要求将认证器与所使用的客户端设备分开时。一个漫游认证器还可以用于保存备份凭证,以防另一个认证器丢失。

6.2.2. 凭证存储模式

认证器可以通过以下两种方式之一存储公钥凭证源

  1. 在嵌入认证器客户端客户端设备中的持久性存储中,例如在安全元素中。这是客户端可发现的公钥凭证源的技术要求。

  2. 通过加密(即封装)凭证私钥,使得只有这个认证器能够解密(即解封装)它,并让生成的密文成为凭证ID,用于公钥凭证源凭证ID依赖方存储,并通过allowCredentials选项在get()操作中返回给认证器,允许认证器解密并使用凭证私钥

    这使得认证器能够拥有无限的凭证私钥存储容量,因为加密的凭证私钥依赖方而非认证器存储——但这意味着以这种方式存储的凭证必须先从依赖方检索回来,认证器才能使用它。

这些存储策略中的哪一种由认证器支持,定义了该认证器凭证存储模式,具体如下:

请注意,可发现凭证支持认证器可以支持两种存储策略。在这种情况下,认证器可以自行决定为不同的凭证使用不同的存储策略,但要受residentKeyrequireResidentKey选项以及create()方法的约束。

6.2.3. 身份验证因素能力

有三类广泛的 身份验证因素 可以用于在 身份验证仪式 中证明身份:你拥有的东西你知道的东西你是的东西。示例包括物理密钥、密码和指纹,分别对应这三类因素。

所有 WebAuthn 认证器 都属于 拥有的东西 类别,但一个支持 认证器 如果支持 用户验证,还可以充当一种或两种额外类型的 身份验证因子。 例如,如果 认证器 能够验证 PIN 码,则该 PIN 码是 你知道的东西,而 生物认证器 可以验证 你是什么。 因此,支持 用户验证认证器多因素能力。相反,一个不支持 多因素能力认证器单因素能力。请注意,单个 多因素能力 认证器 可以支持多种 用户验证 模式,这意味着它可以充当所有三种类型的 身份验证因子

虽然 用户验证 是在 认证器 上本地执行的,而不是由 依赖方 执行,但 认证器 会通过在返回给 依赖方 的签名响应中设置 UV 标志 来指示是否执行了 用户验证。 因此,依赖方 可以使用 UV 标志来验证在 注册认证仪式 中是否使用了额外的 认证因素。进一步地,通过检查 认证器证明声明,可以评估 UV 标志 的真实性。

6.3. 认证器操作

一个WebAuthn 客户端必须连接到认证器,才能调用该认证器的任何操作。此连接定义为认证器会话。认证器必须在会话之间保持隔离。它可以通过仅允许一个会话在任何特定时间存在,或者通过提供更复杂的会话管理来实现这一点。

客户端可以在认证器会话中调用以下操作。

6.3.1. 通过凭据 ID 查找凭据源算法

认证器 authenticator查找凭据 ID credentialId的结果是以下算法的结果:

  1. 如果authenticator可以将credentialId解密为公钥凭据源 credSource

    1. credSource.id设置为credentialId

    2. 返回credSource

  2. 对于每个 公钥凭据源 credSource,在authenticator凭据映射中:

    1. 如果credSource.idcredentialId,则返回credSource

  3. 返回null

6.3.2. The authenticatorMakeCredential 操作

此操作接受以下输入参数:

hash

由客户端提供的序列化客户端数据的哈希

rpEntity

依赖方PublicKeyCredentialRpEntity

userEntity

用户账户的PublicKeyCredentialUserEntity, 包含用户句柄,由依赖方提供。

requireResidentKey

凭据创建的有效常驻密钥要求,由客户端确定的布尔值。

requireUserPresence

布尔常量值true。 它作为伪参数包含在此处,以简化将此抽象认证器模型应用于可能希望使用户存在测试可选的实现,尽管 WebAuthn 并不要求这样做。

requireUserVerification

凭据创建的有效用户验证要求,由客户端确定的布尔值。

credTypesAndPubKeyAlgs

依赖方请求的PublicKeyCredentialType和公钥算法(COSEAlgorithmIdentifier)对的序列。此序列按从最优先到最不优先的顺序排列。认证器尽最大努力创建其可以支持的最优先的凭据。

excludeCredentialDescriptorList

依赖方提供的PublicKeyCredentialDescriptor对象的可选列表,意图是如果认证器已知其中的任何一个,则不应创建新凭据。excludeCredentialDescriptorList包含已知凭据的列表。

enterpriseAttestationPossible

一个布尔值,指示认证器可能返回单独标识的认证。

extensions

客户端基于依赖方(如果有)请求的扩展创建的从扩展标识符到其认证器扩展输入CBOR map

注意:在执行此操作之前,必须通过运行认证器取消操作,终止在认证器会话中进行的所有其他操作。

当调用此操作时,认证器必须执行以下过程:

  1. 检查所有提供的参数是否在语法上格式正确且长度合适。如果不符合,返回等同于"UnknownError" 的错误代码,并终止操作。

  2. 检查是否支持credTypesAndPubKeyAlgs中指定的至少一种PublicKeyCredentialType与加密参数的组合。 如果不支持,返回等同于"NotSupportedError" 的错误代码,并终止操作。

  3. 对于每个excludeCredentialDescriptorList中的descriptor

    1. 如果在此认证器中查找descriptor.id 返回非空,并且返回的项目RP ID类型匹配 rpEntity.idexcludeCredentialDescriptorList.type, 则收集授权手势以确认用户同意创建新凭证。授权手势必须包括用户存在测试。如果用户

      确认同意创建新凭证

      返回等同于"InvalidStateError" 的错误代码,并终止操作。

      不同意创建新凭证

      返回等同于"NotAllowedError" 的错误代码,并终止操作。

      注意:授权手势的目的不是继续创建凭证,而是出于隐私原因,授权披露 descriptor.id 是否绑定到此认证器。 如果用户同意,客户端依赖方可以检测到此并引导用户使用不同的认证器。 如果用户不同意, 认证器不会透露 descriptor.id 是否绑定到它, 并响应为用户只是拒绝创建凭证的同意。

  4. 如果requireResidentKeytrue,且认证器无法存储客户端可发现的公钥凭证源, 返回等同于"ConstraintError" 的错误代码,并终止操作。

  5. 如果requireUserVerificationtrue且认证器无法执行用户验证,返回等同于"ConstraintError" 的错误代码,并终止操作。

  6. 一旦授权手势完成且获得用户同意,生成一个新凭证对象:

    1. 令 (publicKey, privateKey) 为一对新的加密密钥,使用由 PublicKeyCredentialType 和由 credTypesAndPubKeyAlgs 中第一个由该认证器 支持的表示的加密参数的组合。

    2. userHandleuserEntity.id

    3. credentialSource为具有以下字段的新公钥凭证源

      类型

      public-key

      私钥

      privateKey

      rpId

      rpEntity.id

      userHandle

      userHandle

      otherUI

      任何认证器选择包括的其他信息。

    4. 如果requireResidentKeytrue或认证器选择创建一个客户端可发现的公钥凭证源

      1. credentialId为新的凭证ID

      2. credentialSource.id设置为credentialId

      3. credentials为此认证器的凭证映射

      4. 设置credentials[(rpEntity.id, userHandle)]为credentialSource

    5. 否则:

      1. credentialId为序列化和加密credentialSource的结果,以便只有此认证器可以解密它。

  7. 如果在创建新凭证对象时发生任何错误,返回等同于"UnknownError" 的错误代码,并终止操作。

  8. processedExtensions为对extensions中每个支持的扩展标识符认证器扩展输入进行认证器扩展处理迭代的结果。

  9. 如果认证器

    是一个U2F设备

    将新凭证的签名计数器值设为零。(U2F设备可能支持签名计数器,但在创建凭证时不返回计数器。参见[FIDO-U2F-Message-Formats]。)

    支持全局签名计数器

    在生成认证器数据时,使用全局签名计数器的实际值。

    支持每个凭证的签名计数器

    分配计数器,将其与新凭证关联,并将计数器值初始化为零。

    不支持签名计数器

    将新凭证的签名计数器值固定为零。

  10. attestedCredentialData为包括credentialIdpublicKey认证凭证数据字节数组。

  11. authenticatorData为字节数组,指定在§ 6.1 认证器数据中,包括attestedCredentialData作为认证凭证数据,以及(如果有的话)processedExtensions作为扩展

  12. 使用在§ 6.5.4 生成认证对象中指定的过程,为新凭证创建一个认证对象,使用认证器选择的认证声明格式authenticatorDatahash,并考虑enterpriseAttestationPossible的值。有关认证的更多详细信息,请参见§ 6.5 认证

成功完成此操作后,认证器将认证对象返回给客户端。

6.3.3. authenticatorGetAssertion 操作

它接受以下输入参数:

rpId

调用者的RP ID,由用户代理和客户端确定

hash

客户端提供的序列化客户端数据的哈希值

allowCredentialDescriptorList

一个可选的列表,包含描述Relying Party可接受的凭据的PublicKeyCredentialDescriptor对象(可能由客户端过滤),如果有的话。

requireUserPresence

常量布尔值true。 这里将其作为伪参数包含在内,以简化将此抽象认证器模型应用于可能希望使用户在场测试可选的实现,尽管 WebAuthn 不允许这样做。

requireUserVerification

用于断言的有效用户验证要求,由客户端提供的布尔值。

extensions

由客户端基于Relying Party请求的扩展(如果有)创建的CBOR 映射,从扩展标识符到其认证器扩展输入

注意: 在执行此操作之前,必须通过运行authenticatorCancel操作终止认证器会话中的所有其他正在进行的操作。

当调用此方法时,认证器必须执行以下步骤:

  1. 检查所有提供的参数是否语法正确且长度合适。如果不符合要求,返回一个等同于 "UnknownError" 的错误代码并终止操作。

  2. credentialOptions 成为一个新的空 集合,包含 公钥凭证源

  3. 如果提供了 allowCredentialDescriptorList,则 对于每个 descriptor 来自 allowCredentialDescriptorList

    1. credSource 为在此身份验证器中 查找 descriptor.id 的结果。

    2. 如果 credSource 不为 null,则 将其添加credentialOptions 中。

  4. 否则(即没有提供 allowCredentialDescriptorList),对于每个 keycredSource 来自此身份验证器的 凭证映射 credSource 添加到 credentialOptions 中。

  5. 删除credentialOptions 中移除任何其 rpId 不等于 rpId 的项。

  6. 如果 credentialOptions 现在为空,则返回一个等同于 "NotAllowedError" 的错误代码并终止操作。

  7. 提示用户从 credentialOptions 中选择一个 公钥凭证源 selectedCredential。收集确认使用 selectedCredential授权手势,以确认 用户同意。如果 认证器 具有自己的输出功能,授权手势 的提示可以由认证器显示,否则由用户代理显示。

    如果 requireUserVerificationtrue,则 授权手势 必须包含 用户验证

    如果 requireUserPresencetrue,则 授权手势 必须包含 用户在场测试

    如果用户不同意 用户同意,则返回一个相当于 "NotAllowedError" 的错误代码并终止操作。

  8. processedExtensions身份验证器扩展处理 的结果,对于每个 支持的 扩展标识符身份验证器扩展输入extensions 中。

  9. 增加与凭证关联的 签名计数器 或全局 签名计数器 值,具体取决于 身份验证器 实现了哪种方法。身份验证器 如果未实现 签名计数器,则让 签名计数器 的值保持为零。

  10. authenticatorData字节数组,如 § 6.1 身份验证器数据 所指定,包括 processedExtensions(如果有),作为 扩展,并排除 attestedCredentialData

  11. signature断言签名,它是 authenticatorData || hash 的结果,使用 privateKey 来签名 selectedCredential,如图 所示。简单的、无分隔符的连接方式是安全的,因为 身份验证器数据 描述了它自己的长度。序列化的客户端数据的哈希(它的长度可能变化)总是最后一个元素。

    生成一个 断言签名
  12. 如果在生成 断言签名 时发生错误,返回一个等同于 "UnknownError" 的错误代码并终止操作。

  13. 返回给用户代理:
    • selectedCredential.id,如果客户端提供了一个长度为2或更长的凭证列表(即 allowCredentialDescriptorList),或没有提供此类列表。

      注意:如果在 allowCredentialDescriptorList 中,客户端提供了恰好一个凭证且它已成功使用,则该凭证的 凭证ID 不会返回,因为客户端已经知道它。这可以节省在可能受限的连接中传输这些字节,这可能是一个常见情况。

    • authenticatorData

    • signature

    • selectedCredential.userHandle

      注意:返回的 userHandle 值可能是 null,请参见: userHandleResult

如果认证器找不到与指定Relying Party匹配的任何符合指定条件的凭据,则它会终止操作并返回错误。

6.3.4. authenticatorCancel 操作

此操作不接受任何输入参数,也不返回任何结果。

当客户端在认证器会话中调用此操作时,它会终止该认证器会话中当前正在进行的任何authenticatorMakeCredentialauthenticatorGetAssertion操作。认证器停止提示或接受与已取消操作相关的任何用户输入。客户端忽略认证器对已取消操作的任何进一步响应。

如果在没有正在进行的authenticatorMakeCredentialauthenticatorGetAssertion操作的认证器会话中调用此操作,则此操作会被忽略。

6.4. 字符串处理

认证器可能需要存储由Relying Party选择的任意字符串,例如在namedisplayName字段中的PublicKeyCredentialUserEntity对象。本节讨论了处理可能呈现给人类的任意字符串的一些实际影响。

6.4.1. 字符串截断

API 中的每个任意字符串都会根据 身份验证器 可用资源的潜在限制进行适配。如果选择通过字符串值截断来进行适配,那么身份验证器可以截断字符串,以便使其长度等于或大于指定的最小支持长度。此类截断应遵循 UTF-8 序列边界或 字形簇 边界 [UTR29]。这定义了允许的最大截断,身份验证器不得进一步截断。

例如,在中,字符串长度为65字节。如果截断到64字节,则必须出于空间原因删除最后的0x88字节。由于这留下了部分UTF-8序列,因此该序列的剩余部分也可能会被删除。由于这留下了部分字素簇,认证器可以删除该簇的其余部分。

UTF-8编码字符串的末尾,显示不同截断边界的位置。

符合标准的用户代理负责确保Relying Party观察到的认证器行为在字符串处理方面符合此规范。例如,如果已知认证器在被要求存储大字符串时表现不正确,用户代理应为其执行截断以保持从Relying Party视角来看的一致性。执行此操作的用户代理应在字素簇边界处截断。

基于UTF-8序列的截断可能会导致字素簇被截断。这可能导致字素簇呈现为不同的字形,潜在地改变字符串的含义,而不是完全删除字形。

此外,仅在字节边界上截断会导致一个已知问题,用户代理应该意识到这一点:如果认证器使用[FIDO-CTAP],那么来自认证器的未来消息可能包含无效的CBOR,因为该值被类型化为CBOR字符串,因此需要有效的UTF-8。用户代理的任务是处理此问题,以避免让认证器理解字符编码和Unicode字符属性的负担。因此,当与认证器交互时,用户代理应:

  1. 确保发送给认证器的任何字符串都是有效编码的。

  2. 处理字符串截断导致的无效编码情况。例如,可以删除或用U+FFFD替换末尾的任何部分代码点。

6.4.2. 语言和方向编码

为了在上下文中正确显示,字符串的语言和基本方向可能是必需的。此API中的字符串可能需要写入固定功能的认证器,然后再读取并显示在不同的平台上。因此,语言和方向的元数据被编码在字符串本身中,以确保它们原子性地传输。

要在记录为允许语言和方向元数据的字符串中编码这些信息,请在其代码点后附加两个代码点序列:

第一个序列使用代码点U+E0001编码一个语言标签,后跟将语言标签中的ASCII值每个都加上U+E0000。例如,语言标签“en-US”将成为代码点U+E0001、U+E0065、U+E006E、U+E002D、U+E0055、U+E0053。

第二个序列由一个代码点组成,可能是U+200E(“左向右标记”)、U+200F(“右向左标记”)或U+E007F(“取消标签”)。前两个可以用来指示方向性,但只应在需要产生正确结果时使用。(例如,一个RTL字符串以LTR-强字符开头。)值U+E007F是方向无关的,表示语言标签的结束。

因此,字符串“حبیب الرحمان”可能会有两个不同的DOMString值,具体取决于语言是否被编码。(由于方向明确,此示例中不需要方向性标记。)

可能带有语言和方向编码的字符串的消费者应该意识到,截断可能会将语言标签截断为不同但仍然有效的语言。最终的方向性标记或取消标签代码点提供了截断的明确指示。

6.5. 证明

身份验证器 应该在可能的情况下提供某种形式的 证明。如果身份验证器提供证明,基本要求是该 身份验证器 能够为每个 凭证公钥 生成可由 WebAuthn 依赖方 验证的 证明声明。通常,这个 证明声明 包含由 证明私钥 对被证明的 凭证公钥 和一个挑战进行签名,以及提供 证明公钥 来源信息的证书或类似数据,从而使 依赖方 能够做出信任决策。然而,如果没有可用的 证明密钥对,那么身份验证器可以选择对 凭证公钥 进行 自我证明,使用相应的 凭证私钥,或者选择不进行 任何证明。所有这些信息在每次生成新的 公钥凭证 时由 身份验证器 返回,以 证明对象 的总体形式。证明对象 与包含 被证明的凭证数据身份验证器数据证明声明 的关系在下方的 中进行了说明。

如果一个 身份验证器 使用 自我证明不证明,则不会提供任何来源信息供 依赖方 作为信任决策的依据。在这些情况下,身份验证器 不会向 依赖方 提供关于其操作的任何保证。

证明对象 布局,说明所包含的 身份验证器数据(包含 被证明的凭证数据)和 证明声明
此图仅说明 packed 证明声明格式。在 § 8 定义的证明声明格式 中定义了几种其他 证明声明格式

证明对象的一个重要组成部分是 证明声明。这是一种特定类型的已签名数据对象,包含关于 公钥凭证 本身以及创建它的 认证器 的声明。它包含一个 证明签名,该签名使用证明机构的密钥创建(除了 自我证明 的情况,在这种情况下,它是使用 凭证私钥 创建的)。为了正确解释 证明声明依赖方 需要理解这两方面的 证明

  1. 证明声明格式 是签名的表示方式以及各种上下文绑定如何通过 认证器 被合并到证明声明中的方式。换句话说,这定义了声明的语法。各种现有的组件和操作系统平台(例如 TPM 和 Android 操作系统)已定义了 证明声明格式。本规范以可扩展的方式支持各种此类格式,如 § 6.5.2 证明声明格式 中所定义。这些格式本身通过字符串进行标识,如 § 8.1 证明声明格式标识符 中所描述。

  2. 认证类型定义了认证声明及其基础信任模型的语义。具体来说,它定义了依赖方在验证某个认证声明在加密上有效后,如何建立对该声明的信任。本规范支持多种认证类型,详见§ 6.5.3 认证类型

一般来说,证明声明格式证明类型之间没有简单的映射。例如,"packed"(打包)证明声明格式,定义在§ 8.2 打包证明声明格式中,可以与所有证明类型一起使用,而其他格式和类型的适用性则较为有限。

证明 的隐私、安全性和操作特性取决于:

预计大多数 认证器 将支持少量的 证明类型证明声明格式,而 依赖方 将根据政策决定它们接受哪些 证明类型依赖方 还需要理解它们信任的 认证器 的特性,基于它们对这些 认证器 的了解。例如,FIDO 元数据服务 [FIDOMetadataService] 提供了一种访问此类信息的方式。

6.5.1. Attested Credential Data

已认证的凭证数据 是在生成给定凭证的 证明对象 时添加到 认证器数据 中的一个可变长度字节数组。其格式如 所示。

Name Length (in bytes) Description
aaguid 16 认证器的 AAGUID。
credentialIdLength 2 Credential ID 的字节长度 L,16 位无符号大端整数。
credentialId L Credential ID
credentialPublicKey variable 凭证公钥,使用 [RFC8152] 第 7 节定义的 COSE_Key 格式编码,并使用 CTAP2 规范的 CBOR 编码形式。COSE_Key 编码的 凭证公钥 必须包含 "alg" 参数,并且不得包含任何其他可选参数。"alg" 参数必须包含 COSEAlgorithmIdentifier 值。编码的 凭证公钥 还必须包含相关密钥类型规范所规定的任何其他必需参数,即 "kty" 和算法 "alg" 所需的参数(见 [RFC8152] 第 8 节)。
已认证的凭证数据 的布局。名称列中的名称仅供本文档内部引用,在 已认证的凭证数据 的实际表示中不存在。
6.5.1.1. COSE_Key格式编码的credentialPublicKey值的示例

本节提供了用于 ES256、PS256 和 RS256 签名算法的 COSE_Key 编码椭圆曲线和 RSA 公钥示例。这些示例遵循上文定义的 credentialPublicKey 值的规则,并以 CDDL [RFC8610] 进行展示以便于理解。

[RFC8152] 第 7 节 定义了所有 COSE_Key 编码密钥的一般框架。其他规范的特定算法的具体密钥类型在 [RFC8152] 的其他章节中定义。

以下是一个 COSE_Key 编码的椭圆曲线公钥的示例,使用 EC2 格式(见 [RFC8152] 第 13.1 节),在 P-256 曲线上,与 ES256 签名算法(使用 ECDSA w/ SHA-256,见 [RFC8152] 第 8.1 节 一起使用):

{
  1:   2,  ; kty: EC2 key type
  3:  -7,  ; alg: ES256 signature algorithm
 -1:   1,  ; crv: P-256 curve
 -2:   x,  ; x-coordinate as byte string 32 bytes in length
           ; e.g., in hex: 65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d
 -3:   y   ; y-coordinate as byte string 32 bytes in length
           ; e.g., in hex: 1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c
}

以下是上述椭圆曲线公钥在 CTAP2 规范的 CBOR 编码形式中的编码示例,包含了空白和换行符以便于理解并与上文的 CDDL [RFC8610] 的展示相匹配:

A5
   01  02

   03  26

   20  01

   21  58 20   65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d

   22  58 20   1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c

以下是一个 COSE_Key 编码的 2048 位 RSA 公钥示例(见 [RFC8230] 第 4 节),与 PS256 签名算法(使用 RSASSA-PSS 和 SHA-256,见 [RFC8230] 第 2 节一起使用):

{
  1:   3,  ; kty: RSA key type
  3: -37,  ; alg: PS256
 -1:   n,  ; n: RSA modulus n byte string 256 bytes in length
           ; e.g., in hex (middle bytes elided for brevity): DB5F651550...6DC6548ACC3
 -2:   e   ; e: RSA public exponent e byte string 3 bytes in length
           ; e.g., in hex: 010001
}

以下是与 RS256 签名算法(使用 RSASSA-PKCS1-v1_5 和 SHA-256)一起使用的相同 COSE_Key 编码 RSA 公钥示例:

{
  1:   3,  ; kty: RSA key type
  3:-257,  ; alg: RS256
 -1:   n,  ; n: RSA modulus n byte string 256 bytes in length
           ; e.g., in hex (middle bytes elided for brevity): DB5F651550...6DC6548ACC3
 -2:   e   ; e: RSA public exponent e byte string 3 bytes in length
           ; e.g., in hex: 010001
}

6.5.2. 认证声明格式

如上所述,认证声明格式是一种数据格式,表示由认证器对一组上下文绑定进行的加密签名。每个认证声明格式必须使用以下模板定义:

指定的认证声明格式的初始列表位于§ 8 定义的认证声明格式

6.5.3. 证明类型

WebAuthn 支持几种证明类型,定义了证明声明及其底层信任模型的语义:

注意: 本规范未定义显式表达证明类型的数据结构,这些类型由验证器使用。信赖方在从事证明声明验证时——即调用navigator.credentials.create()时选择一个证明传递,而不是none,并验证接收到的证明声明,将确定使用的证明类型作为验证的一部分。请参阅§ 8 已定义的证明声明格式中的“验证过程”小节。另见§ 14.4.1 证明隐私。对于本节中定义的除自我证明以外的所有证明类型信赖方验证将遵循§ 7.1 注册新凭证步骤 21 中的匹配信任路径至可接受的根证书。区分这些证明类型主要是作为确定证明是否符合信赖方政策的手段。

基本证明 (基本)

在基本证明的情况下,[UAFProtocol],身份验证器的 证明密钥对 是特定于身份验证器的“型号”,即一批身份验证器。因此,相同或相似型号的身份验证器通常共享相同的 证明密钥对。有关更多信息,请参见 § 14.4.1 证明隐私

基本证明 也称为 批量证明

自我证明 (自我)

自我声明 的情况下,也称为代理基本声明 [UAFProtocol],身份验证器没有任何特定的 声明密钥对。相反,它使用 凭证私钥 来创建 声明签名。 没有对 声明私钥 进行有效保护措施的身份验证器通常会使用这种声明类型。

证明 CA (证明 CA)

在这种情况下,一个 身份验证器 基于受信平台模块(TPM),并持有一个特定于身份验证器的 "背书密钥"(EK)。该密钥用于与受信的第三方安全通信,第三方是 背书CA [TCG-CMCProfile-AIKCertEnroll](以前称为 "隐私CA")。该 身份验证器 可以生成多个 背书身份密钥对(AIK),并请求 背书CA 为每个密钥对签发一个AIK证书。 使用这种方法,此类 身份验证器 可以将背书密钥(EK,作为一个全局关联句柄)的暴露限制在背书CA之间。可以为每个 身份验证器 生成的 公钥凭证 单独请求AIK,并将其作为 背书证书 传递给 依赖方

注: 这一概念通常会导致多个证明证书。最近请求的证明证书称为“活动”的。

匿名化 CA (匿名化 CA)

在这种情况下,身份验证器 使用一个 匿名化 CA,该 CA 会动态生成每个 凭证证明证书,使得提供给 依赖方证明声明 不提供唯一的可识别信息,例如,可能用于跟踪的内容。

注意: 证明声明 传递的 证明 类型为 类型 AttCAAnonCA 使用与 类型 Basic 相同的数据结构,因此这三种证明类型通常只能通过外部提供的关于 证明证书 内容的知识来区分,这些证书包含在 证明声明 中。

没有证明声明 ()

在这种情况下,没有可用的证明信息。另见 § 8.7 无证明声明格式

6.5.4. 生成证明对象

要生成一个证明对象(参见:图 6),需要给定以下内容:

attestationFormat

一个证明声明格式

authData

包含验证器数据的字节数组。

hash

序列化客户端数据的哈希值

验证器必须:

  1. attStmt成为运行attestationFormat签名过程的结果,给定authDatahash

  2. fmt成为attestationFormat证明声明格式标识符

  3. 返回证明对象,作为包含以下语法的 CBOR 映射,并用此算法初始化的变量填充:

        attObj = {
                    authData: bytes,
                    $$attStmtType
                 }
    
        attStmtTemplate = (
                              fmt: text,
                              attStmt: { * tstr => any } ; Map is filled in by each concrete attStmtType
                          )
    
        ; Every attestation statement format must have the above fields
        attStmtTemplate .within $$attStmtType
    

6.5.5. 打包证明、FIDO U2F 证明和声明签名的签名格式

建议任何新定义的证明格式不要使用 ASN.1 编码,而是使用与 [RFC8152][RFC8230] 中定义的 COSE 签名使用的表示方法相同的固定长度字节数组来表示签名,无需内部结构。

以下签名格式定义满足此要求,并作为派生其他未明确提及的签名算法的示例:

7. WebAuthn 证明对象 操作

一个 注册身份验证仪式WebAuthn 依赖方 创建一个 PublicKeyCredentialCreationOptionsPublicKeyCredentialRequestOptions 对象,分别编码该 仪式 的参数。依赖方 应谨慎避免在此阶段泄漏敏感信息; 详情请见 § 14.6.2 用户名枚举

在成功执行 create()get()依赖方 的脚本 将接收到一个 PublicKeyCredential 包含一个 AuthenticatorAttestationResponseAuthenticatorAssertionResponse 结构,分别来自客户端。然后,它必须将该结构的内容传送到 依赖方 服务器, 使用本规范范围之外的方法。此部分描述了 依赖方 在收到这些结构后的操作。

7.1. 注册一个新的凭证

为了执行注册仪式证明对象 必须按如下步骤进行:

  1. options 成为一个新的 PublicKeyCredentialCreationOptions 结构,配置为 依赖方 在仪式中的需求。

  2. 调用 navigator.credentials.create() 并将 options 作为 publicKey 选项传入。 让 credential 成为成功解决的承诺的结果。 如果承诺被拒绝,则中止仪式并显示用户可见的错误,或者根据拒绝承诺时的上下文引导用户体验。例如,如果承诺因 错误代码等于 "InvalidStateError" 被拒绝,用户可能被指示使用其他的 身份验证器。 有关不同错误上下文和导致这些情况的情形,请参见 § 6.3.2 身份验证器创建凭证操作

  3. responsecredential.response。 如果 response 不是 AuthenticatorAttestationResponse 的实例, 则中止仪式并显示用户可见的错误。

  4. clientExtensionResults 为调用 credential.getClientExtensionResults() 的结果。

  5. JSONtext 为运行 UTF-8 解码 后的结果,该解码作用于 response.clientDataJSON 的值。

    注意: 只要结果与 UTF-8 解码 算法的结果相同, 使用任何实现的 UTF-8 解码 都是可以接受的。特别地,任何前导字节顺序标记(BOM)必须被去除。

  6. C,作为在凭证创建过程中声明的 客户端数据, 成为对 JSONtext 运行特定实现的 JSON 解析器的结果。

    注意: C 可以是任何特定实现的数据结构表示,只要 C 的组件是可以引用的,正如此算法所要求的。

  7. 验证 C.type 的值是否为 webauthn.create

  8. 验证 C.challenge 的值是否等于 options.challenge 的 base64url 编码。

  9. 验证 C.origin 的值是否与 依赖方来源 匹配。

  10. 验证 C.tokenBinding.status 的值是否与通过 TLS 连接获得 声明 时的 Token Binding 的状态相匹配。如果在该 TLS 连接上使用了 Token Binding,还需验证 C.tokenBinding.id 的值是否与该连接的 base64url 编码 匹配,该编码表示该连接的 Token Binding ID

  11. hash成为使用SHA-256对response.clientDataJSON值进行哈希计算的结果。

  12. attestationObject字段中的AuthenticatorAttestationResponse结构执行CBOR解码,以获取证明对象格式fmt认证器数据authData以及证明对象attStmt

  13. 验证authData中的rpIdHash是否为依赖方期望的RP ID的SHA-256哈希值。

  14. 验证authData中的标志用户存在位是否已设置。

  15. 如果此注册要求用户验证,请验证authData中的标志用户验证位是否已设置。

  16. 验证authData中的凭证公钥中的"alg"参数是否与alg属性匹配,options.pubKeyCredParams

  17. 验证 clientExtensionResults 中的 客户端扩展输出 的值,以及 authData扩展 中的 身份验证器扩展输出 是否符合预期,考虑到在 options.extensions 中提供的 客户端扩展输入 值,以及 依赖方 关于未请求扩展的任何特定策略,即那些未在 options.extensions 中指定的扩展。在一般情况下,“符合预期”的含义是特定于 依赖方 和使用的扩展。

    注意: 客户端平台 可以执行本地策略,设置额外的 身份验证器扩展客户端扩展,从而导致在 身份验证器扩展输出客户端扩展输出 中出现原本未在 options.extensions 中指定的值。依赖方 必须准备好处理这种情况, 无论是忽略未请求的扩展,还是拒绝证明。依赖方 可以根据本地策略和使用的扩展做出此决定。

    注意: 由于对于 客户端身份验证器 来说,所有扩展都是可选的,依赖方 必须准备好处理以下情况:即使请求了扩展,可能没有所有扩展被处理。

  18. 通过在fmt与支持的WebAuthn证明对象格式标识符值集合之间执行USASCII区分大小写匹配来确定证明对象格式。WebAuthn证明对象格式标识符值的最新注册列表由IANA "WebAuthn Attestation Statement Format Identifiers"注册表[IANA-WebAuthn-Registries]维护,该注册表由[RFC8809]建立。

  19. 验证 attStmt 是否是一个正确的 证明声明,通过使用 证明签名,通过使用 证明声明格式 fmt验证程序,使用 attStmtauthDatahash

    注意: 每种 证明声明格式 都指定了其自己的 验证程序。请参阅 § 8 定义的证明声明格式 了解初步定义的格式,并查看 [IANA-WebAuthn-Registries] 获取最新列表。

  20. 如果验证成功,从受信任的来源或策略中获取该证明类型和证明声明格式 fmt 的可接受信任锚(即证明根证书)列表。例如,FIDO 元数据服务 [FIDOMetadataService] 提供了一种获取此类信息的方法,使用 aaguidattestedCredentialData 中,在 authData 中。

  21. 使用第 19 步中 验证程序 的输出评估证明的可信度,具体如下:

  22. 检查 credentialId 是否尚未注册到其他用户。如果请求注册的凭证已注册给其他用户,则 依赖方 应该失败此 注册仪式,或者可以决定接受注册,例如删除旧的注册。

  23. 如果证明声明 attStmt 验证成功且被认为可信,则将新凭证注册到在 options.user 中指定的账户:

    强烈推荐同时:

  24. 如果证明声明 attStmt 验证成功,但根据第 21 步的判断不可信,则 依赖方 应该失败此 注册仪式

    注意: 然而,如果策略允许,依赖方 可以注册 凭证 ID 和凭证公钥,但将凭证视为具有 自我证明(见 § 6.5.3 证明类型)。如果这样做,依赖方 在声明没有加密证明证明该 公钥凭证 是由特定的 身份验证器 模型生成的。

    请参阅 [FIDOSecRef][UAFProtocol] 获取更详细的讨论。

认证对象 的验证要求 依赖方 在上述第20步中具有一种受信任的方法来确定可接受的信任锚。 此外,如果使用证书,依赖方 必须能够访问中间 CA 证书的证书状态信息。依赖方 还必须能够构建认证证书链, 如果客户端没有在认证信息中提供该链的话。

7.2. 验证认证声明

为了执行认证仪式证明对象必须按如下步骤进行:

  1. options 为一个新的 PublicKeyCredentialRequestOptions 结构体,按照 依赖方 的需求进行配置以进行仪式。

    如果 options.allowCredentials 存在, 则每个 transports 成员应设置为注册相应凭证时通过 credential.response.getTransports() 返回的值。

  2. 调用 navigator.credentials.get() 并将 options 作为 publicKey 选项传递。 设 credential 为成功解析的 promise 的结果。 如果 promise 被拒绝,则使用可见的错误中止仪式,或根据拒绝的 promise 中可用的上下文指导用户体验。有关不同错误上下文和导致它们的情况的信息,请参见 § 6.3.3 身份验证器获取断言操作

  3. responsecredential.response。 如果 response 不是 AuthenticatorAssertionResponse 的实例, 则使用可见的错误中止仪式。

  4. clientExtensionResults 为调用 credential.getClientExtensionResults() 的结果。

  5. 如果 options.allowCredentials 不为空, 验证 credential.id 是否标识了 options.allowCredentials 中列出的某个 公钥凭证

  6. 识别正在进行身份验证的用户,并验证该用户是否为 公钥凭证来源 credentialSource 的所有者,该来源由 credential.id 标识:

    如果在启动 身份验证仪式 之前已识别出用户,例如通过用户名或Cookie,

    验证识别的用户是否为 credentialSource 的所有者。如果 response.userHandle 存在, 则设 userHandle 为其值。验证 userHandle 是否也映射到相同的用户。

    如果在启动 身份验证仪式 之前未识别出用户,

    验证 response.userHandle 是否存在,并且由该值识别的用户是 credentialSource 的所有者。

  7. 使用 credential.id (或者 credential.rawId, 如果 base64url 编码 对你的使用场景不合适),查找对应的 凭证公钥,并让 credentialPublicKey 为该 凭证公钥

  8. cDataauthDatasig 分别表示 responseclientDataJSONauthenticatorData, 和 signature

  9. JSONtext 为对 cData 运行 UTF-8 解码 的结果。

    注意: 任何实现的 UTF-8 解码 都是可以接受的,只要它产生的结果与 UTF-8 解码 算法的结果相同。特别地,任何前导字节顺序标记(BOM)必须被去除。

  10. C,即作为签名使用的 客户端数据,为运行实现特定的 JSON 解析器对 JSONtext 解析后的结果。

    注意: C 可以是任何实现特定的数据结构表示形式,只要 C 的组件可以被引用,符合该算法的要求。

  11. 验证 C.type 的值为字符串 webauthn.get

  12. 验证 C.challenge 的值是否等于 options.challenge 的 base64url 编码。

  13. 验证 C.origin 的值与 Relying Partyorigin 匹配。

  14. 验证 C.tokenBinding.status 的值与该 TLS 连接使用的 Token Binding 状态匹配。如果该 TLS 连接使用了 Token Binding,还需要验证 C.tokenBinding.id 与该连接的 base64url 编码Token Binding ID 匹配。

  15. 验证authData中的rpIdHash是否为依赖方期望的RP ID的SHA-256哈希值。

    注意:如果使用appid扩展,则此步骤需要一些特殊逻辑。详见§ 10.1 FIDO AppID扩展 (appid)

  16. 验证 User Present 标志位是否已在 flags 中设置。

  17. 如果 用户验证 对此断言是必需的,验证 用户验证 位在 标志 中的 authData 是否已设置。

  18. 验证clientExtensionResults中的客户端扩展输出的值与authData扩展中的认证器扩展输出是否符合预期,考虑到在options.扩展中提供的客户端扩展输入值以及依赖方关于非请求的扩展(即那些未作为options.扩展一部分指定的扩展)的任何特定策略。在一般情况下,“符合预期”的含义取决于依赖方以及正在使用的扩展。

    注意: 客户端平台 可以执行本地策略,设置额外的 认证器扩展客户端扩展,从而导致在 认证器扩展输出客户端扩展输出 中出现未在最初的 options.extensions 中指定的值。依赖方 必须准备好处理这种情况,无论是忽略未请求的扩展,还是拒绝断言。依赖方 可以根据本地策略和使用的扩展来做出这一决定。

    注意: 由于所有扩展对 客户端认证器 都是可选的,依赖方 也必须准备好处理没有或不是所有请求的扩展被处理的情况。

  19. hash 为对 cData 使用 SHA-256 计算的哈希值。

  20. 使用 credentialPublicKey,验证 sig 是否是对 authDatahash 的二进制串联的有效签名。

    注意: 此验证步骤与 FIDO U2F 认证器生成的签名兼容。参见 § 6.1.2 FIDO U2F 签名格式兼容性

  21. storedSignCount 为与 credential.id 关联的存储的 签名计数器 值。如果 authData.signCount 非零或 storedSignCount 非零,则执行以下子步骤:

    • 如果 authData.signCount 大于 storedSignCount

      大于 storedSignCount
      storedSignCount 更新为 authData.signCount 的值。
      小于或等于 storedSignCount
      这是一个信号,表明认证器可能被克隆,即至少有两个 凭证私钥 副本可能存在并同时使用。依赖方 应该将此信息纳入他们的风险评分。无论 依赖方 是否更新 storedSignCount,或者是否失败 认证仪式,都取决于 依赖方 的具体决定。
  22. 如果所有上述步骤成功,则根据需要继续进行 认证仪式。否则,失败此 认证仪式

8. 定义的证明声明格式

WebAuthn 支持可插拔的证明声明格式。本节定义了一组初始的此类格式。

8.1. 证明声明格式标识符

证明声明格式通过一个字符串标识,称为证明声明格式标识符,由证明声明格式的作者选择。

证明声明格式标识符应在 IANA 的 "WebAuthn 证明声明格式标识符" 注册表中注册 [IANA-WebAuthn-Registries],该注册表由[RFC8809]建立。 所有注册的证明声明格式标识符彼此之间都是唯一的。

未注册的证明声明格式标识符应使用小写的反向域名命名,使用 开发人员注册的域名,以确保标识符的唯一性。所有证明声明格式标识符必须 最多为32个八位字节,且只能包含可打印的USASCII字符,不包括反斜杠和双引号, 即,在[RFC5234]中定义的VCHAR,但不包括 %x22 和 %x5c。

注意:这意味着基于域名的证明声明格式标识符必须仅包含LDH标签[RFC5890]

实现必须区分大小写地匹配 WebAuthn 证明声明格式标识符。

可能存在多个版本的证明声明格式应在其标识符中包含一个版本。实际上, 不同的版本因此被视为不同的格式,例如packed2作为 § 8.2 打包证明声明格式的新版本。

以下各节展示了一组当前定义和注册的证明声明格式及其标识符。 注册的WebAuthn 扩展的最新列表由 IANA 的 "WebAuthn 证明声明格式标识符" 注册表维护 [IANA-WebAuthn-Registries],该注册表由[RFC8809]建立。

8.2. 打包证明声明格式

这是一个WebAuthn优化的证明声明格式。它使用非常紧凑但仍可扩展的编码方法。它是 由资源有限的验证器(例如安全元素)实现的。

证明声明格式标识符

packed

支持的证明类型

基本自我AttCA

语法

打包证明声明的语法定义如下的CDDL:

    $$attStmtType //= (
                          fmt: "packed",
                          attStmt: packedStmtFormat
                      )

    packedStmtFormat = {
                           alg: COSEAlgorithmIdentifier,
                           sig: bytes,
                           x5c: [ attestnCert: bytes, * (caCert: bytes) ]
                       } //
                       {
                           alg: COSEAlgorithmIdentifier
                           sig: bytes,
                       }

这些字段的语义如下:

alg

证明签名使用的算法标识符包含在COSEAlgorithmIdentifier中。

sig

包含证明签名的字节字符串。

x5c

此数组的元素包含attestnCert及其证书链(如果有), 每个都以X.509格式编码。证明 证书attestnCert必须是数组中的第一个元素。

attestnCert

证明证书,以X.509格式编码。

签名过程

此证明声明格式的签名过程类似于生成断言签名的过程

  1. authenticatorData表示证明的验证器数据, 令clientDataHash表示序列化客户端数据的哈希值

  2. 如果使用基本AttCA 证明, 验证器通过连接authenticatorDataclientDataHash来生成sig,并使用通过验证器特定机制选择的证明私钥对结果进行签名。它将x5c设置为attestnCert,后面跟随相关的 证书链(如果有)。它将alg设置为 证明私钥的算法。

  3. 如果使用自我证明,验证器通过连接authenticatorDataclientDataHash来生成sig, 并使用凭证私钥对结果进行签名。它将alg设置为 凭证私钥的算法,并省略其他字段。

验证过程

给定验证过程的输入 attStmt, authenticatorDataclientDataHash验证过程 如下:

  1. 验证attStmt是否为符合上述语法定义的有效CBOR,并对其执行CBOR解码以提取 包含的字段。

  2. 如果x5c存在:

    • 验证sig是否是使用 alg中指定的算法,通过attestnCert中的证明公钥对 authenticatorDataclientDataHash的连接进行签名的有效签名。

    • 验证attestnCert是否符合§ 8.2.1 打包证明声明 证书要求中的要求。

    • 如果attestnCert包含OID为 1.3.6.1.4.1.45724.1.1.4 (id-fido-gen-ce-aaguid)的扩展,验证 该 扩展的值是否与 aaguid 中的值一致authenticatorData

    • 可选地,检查x5c并咨询外部提供的知识以 确定attStmt是否传达了基本AttCA证明。

    • 如果成功,返回表示证明类型 基本AttCA或不确定性以及 证明信任路径 x5c的实现特定值。

  3. 如果x5c不存在,则使用自我证明

    • 验证alg是否与authenticatorData中的 credentialPublicKey 的算法匹配。

    • 验证sig是否是使用alg的算法,通过凭证公钥对 authenticatorDataclientDataHash的连接进行签名的有效签名。

    • 如果成功,返回表示证明类型 自我的实现特定值和一个空的 证明信任路径

8.2.1. 打包证明声明证书要求

证明证书必须具有以下字段/扩展:

8.3. TPM证明声明格式

此证明声明格式通常由使用可信平台模块(TPM)作为其加密 引擎的验证器使用。

证明声明格式标识符

tpm

支持的证明类型

AttCA

语法

TPM证明声明的语法如下:

    $$attStmtType // = (
                           fmt: "tpm",
                           attStmt: tpmStmtFormat
                       )

    tpmStmtFormat = {
                        ver: "2.0",
                        (
                            alg: COSEAlgorithmIdentifier,
                            x5c: [ aikCert: bytes, * (caCert: bytes) ]
                        )
                        sig: bytes,
                        certInfo: bytes,
                        pubArea: bytes
                    }

以上字段的语义如下:

ver

签名符合的TPM规范版本。

alg

COSEAlgorithmIdentifier 包含用于生成证明签名的算法标识符。

x5c

aikCert后面是其证书链,以X.509编码。

aikCert

用于证明的AIK证书,以X.509编码。

sig

证明签名,形式为 TPMT_SIGNATURE 结构,如[TPMv2-Part2]第11.3.4节中所规定。

certInfo

TPMS_ATTEST结构,其中包含上面生成的签名,如[TPMv2-Part2]第 10.12.8节中规定。

pubArea

TPMT_PUBLIC结构(见[TPMv2-Part2]第12.2.4节),由TPM用于 表示凭证公钥。

签名过程

authenticatorData表示证明的验证器数据, 令clientDataHash表示序列化客户端数据的哈希值

authenticatorDataclientDataHash连接 形成 attToBeSigned

使用[TPMv2-Part3]第18.2节中规定的过程生成签名, 使用证明私钥 并将extraData参数设置为使用"alg"签名算法的哈希算法生成的attToBeSigned摘要。 (对于"RS256"算法,这将是SHA-256摘要。)

pubArea字段设置为凭证公钥的公共区域,将 certInfo字段设置为相同名称的 输出参数,并将sig字段设置为从上述过程获得的签名。

验证过程

给定验证过程的输入 attStmt, authenticatorDataclientDataHash验证过程如下:

验证attStmt是否为符合上述语法定义的有效CBOR,并对其执行 CBOR解码以提取 包含的字段。

验证由parametersunique字段指定的 公钥是否与 credentialPublicKey 中的公钥一致 attestedCredentialDataauthenticatorData中。

authenticatorDataclientDataHash连接形成 attToBeSigned

验证certInfo是否有效:

  • 验证magic是否设置为TPM_GENERATED_VALUE

  • 验证type是否设置为TPM_ST_ATTEST_CERTIFY

  • 验证extraData是否设置为使用"alg"中使用的哈希算法生成的 attToBeSigned的哈希值。

  • 验证attested是否包含TPMS_CERTIFY_INFO结构,如[TPMv2-Part2]第 10.12.3节中规定, 其name字段包含pubArea的有效名称, 如使用pubArea中的nameAlg字段指定的算法,使用[TPMv2-Part1]第16节中规定的过程生成的有效名称。

  • 验证x5c是否存在。

  • 请注意"标准证明结构"中的其余字段[TPMv2-Part1]第31.2节中, 即 qualifiedSignerclockInfofirmwareVersion被忽略。 这些字段可以用作风险引擎的输入。

  • 验证sig是否为certInfo上的有效签名,使用 证明 公钥aikCert,并使用 alg中指定的算法。

  • 验证aikCert是否符合§ 8.3.1 TPM 证明声明证书 要求中的要求。

  • 如果aikCert包含OID为1.3.6.1.4.1.45724.1.1.4的扩展 (id-fido-gen-ce-aaguid),验证该扩展的值是否与 aaguidauthenticatorData的一致。

  • 如果成功,返回表示证明类型 AttCA证明信任路径x5c的实现特定值。

8.3.1. TPM证明声明证书要求

TPM 证明证书 必须包含以下字段/扩展:

8.4. Android Key Attestation Statement Format

当相关的 身份验证器 是在 Android "N" 或更高版本平台上的 平台身份验证器 时,证明语句基于 Android 密钥证明。在这些情况下,证明语句 由在安全操作环境中运行的组件生成,但 用于证明的身份验证器数据 是在此环境之外生成的。 WebAuthn 依赖方 应该检查 声称已用于证明的身份验证器数据 是否与证明证书扩展数据的字段一致。

证明语句格式标识符

android-key

支持的证明类型

基本

语法

Android 密钥证明语句简单地包含 Android 证明语句,这是一系列 DER 编码的 X.509 证书。参见 Android 开发者文档。 其语法定义如下:

    $$attStmtType //= (
                      fmt: "android-key",
                      attStmt: androidStmtFormat
                  )

androidStmtFormat = {
                      alg: COSEAlgorithmIdentifier,
                      sig: bytes,
                      x5c: [ credCert: bytes, * (caCert: bytes) ]
                    }

签名过程

authenticatorData 表示 用于证明的身份验证器数据,并让 clientDataHash 表示 序列化客户端数据的哈希

通过调用 keyStore.getCertificateChain(myKeyUUID) 请求 Android 密钥证明,提供 clientDataHash 作为挑战值(例如,使用 setAttestationChallenge)。将 x5c 设置为返回的值。

身份验证器通过连接 authenticatorDataclientDataHash,并使用凭证私钥对结果进行签名生成 sig。它将 alg 设置为签名格式的算法。

验证过程

给定 验证过程输入 attStmtauthenticatorDataclientDataHash验证过程如下:

  • 验证 attStmt 是否为符合上述语法的有效 CBOR,并对其进行 CBOR 解码以提取包含的字段。

  • 验证 sig 是否为有效签名,该签名是针对 authenticatorDataclientDataHash 的连接,使用 x5c 中第一个证书的公钥和 alg 中指定的算法。

  • 验证 x5c 中第一个证书的公钥是否与 credentialPublicKey 相匹配,该公钥位于 attestedCredentialData 中,位于 authenticatorData 中。

  • 验证 attestationChallenge 字段是否与 证明证书扩展数据 中的 clientDataHash 相同。

  • 使用证明证书中的适当授权列表 扩展数据 验证以下内容:

    • 在任何授权列表(softwareEnforcedteeEnforced)中都不应出现 AuthorizationList.allApplications 字段,因为 PublicKeyCredential 必须被 限定于 RP ID

    • 对于以下内容,如果 RP 仅希望接受来自受信执行环境的密钥,请仅使用 teeEnforced 授权列表,否则使用 teeEnforcedsoftwareEnforced 的联合。

      • AuthorizationList.origin 字段的值应等于 KM_ORIGIN_GENERATED

      • AuthorizationList.purpose 字段的值应等于 KM_PURPOSE_SIGN

  • 如果成功,返回表示 证明类型 基本证明信任路径 x5c 的实现特定值。

8.4.1. Android密钥证明声明证书要求

Android密钥证明的证明证书Android密钥证明证书扩展数据由OID 1.3.6.1.4.1.11129.2.1.17标识,其架构定义在Android开发者文档中。

8.5. Android SafetyNet 证明声明格式

认证器在某些Android平台上是平台认证器时,证明声明可能基于SafetyNet API。在这种情况下,认证器数据完全由SafetyNet API的调用者(通常是在Android平台上运行的应用程序)控制,证明声明提供了一些关于平台健康状况和调用应用程序身份的声明(详情请参见SafetyNet文档)。

证明声明格式标识符

android-safetynet

支持的证明类型

基本

语法

Android 证明声明的语法定义如下:

    $$attStmtType //= (
                                      fmt: "android-safetynet",
                                      attStmt: safetynetStmtFormat
                                  )
                
                safetynetStmtFormat = {
                                          ver: text,
                                          response: bytes
                                      }
                

上述字段的语义如下:

ver

负责提供 SafetyNet API 的 Google Play 服务的版本号。

response

The UTF-8 编码的 getJwsResult() 调用结果,来自 SafetyNet API。此值是一个 JWS [RFC7515] 对象(参见 SafetyNet 在线文档),采用紧凑序列化格式。

签名过程

authenticatorData 表示 证明的身份验证器数据, 让 clientDataHash 表示 已序列化客户端数据的哈希值

authenticatorDataclientDataHash 拼接,执行 SHA-256 哈希,得到 attToBeSigned

请求一个 SafetyNet 证明,提供 attToBeSigned 作为随机数值。将 response 设置为结果,将 ver 设置为 身份验证器中运行的 Google Play 服务版本。

验证过程

给定验证过程输入attStmtauthenticatorDataclientDataHash验证过程如下:

  • 验证 attStmt 是否符合上述语法的有效 CBOR,并对其进行 CBOR 解码,以提取其中的字段。

  • 验证 response 是否是版本为 ver 的有效 SafetyNet 响应,按照 SafetyNet 在线文档 中的步骤进行验证。 截至目前,SafetyNet 响应只有一种格式,且 ver 被保留用于未来使用。

  • 验证 response 中有效负载的 nonce 属性是否与 authenticatorDataclientDataHash 的 SHA-256 哈希值的 Base64 编码相同。

  • 验证 SafetyNet 响应是否确实来自 SafetyNet 服务,按照 SafetyNet 在线文档 中的步骤进行验证。

  • 如果验证成功,返回表示 证明类型 基本证明信任路径 x5c 的实现特定值。

8.6. FIDO U2F 证明声明格式

该证明声明格式用于使用[FIDO-U2F-Message-Formats]中定义的格式的FIDO U2F认证器。

证明声明格式标识符

fido-u2f

支持的证明类型

基础, AttCA

语法

FIDO U2F证明声明的语法定义如下:

    $$attStmtType //= (
                          fmt: "fido-u2f",
                          attStmt: u2fStmtFormat
                      )

    u2fStmtFormat = {
                        x5c: [ attestnCert: bytes ],
                        sig: bytes
                    }

上述字段的语义如下:

x5c

一个包含X.509格式的证明证书的单元素数组。

sig

证明签名。 签名是基于认证器发送给客户端的U2F注册响应消息的(原始)[FIDO-U2F-Message-Formats]计算的。

签名过程

如果 凭证公钥认证凭证 不是算法 -7("ES256"),则停止并返回错误。否则,令 authenticatorData 表示 认证数据,并令 clientDataHash 表示 序列化客户端数据的哈希值。(由于使用 SHA-256 哈希化序列化的 客户端数据clientDataHash 将是 32 字节长。)

生成一个注册响应消息,如 [FIDO-U2F-Message-Formats] 第 4.3 节 所指定的,应用参数设置为所给的 RP ID 的 SHA-256 哈希,凭证 的范围 scoped,挑战参数设置为 clientDataHash,密钥句柄参数设置为所给凭证的 凭证 ID。将该注册响应消息的原始签名部分(即,不包括 用户公钥、密钥句柄和认证证书)设置为 sig,并将认证公钥的认证证书设置为 x5c

验证过程

给定 验证过程输入 attStmtauthenticatorDataclientDataHash验证过程如下:

  1. 验证 attStmt 是否符合上述定义的 CBOR 语法,并对其进行 CBOR 解码以提取 包含的字段。

  2. 检查 x5c 是否恰好包含一个元素,并将 attCert 设为该元素。 设 certificate public key 为由 attCert 传递的公钥。如果 certificate public key 不是 P-256 曲线上的椭圆曲线(EC)公钥, 终止此算法并返回适当的错误。

  3. authenticatorData 中提取声明的 rpIdHash,以及从 authenticatorData.attestedCredentialData 中提取声明的 credentialIdcredentialPublicKey

  4. 将 COSE_KEY 格式的 credentialPublicKey(参见 第 7 节[RFC8152])转换为原始 ANSI X9.62 公钥 格式(参见 第 3.6.2 节 公钥表示格式[FIDO-Registry])。

    • xcredentialPublicKey 中对应于 "-2" 键(表示 x 坐标)的值, 并确认其大小为 32 字节。如果大小不同或未找到 "-2" 键,终止此算法并返回 适当的错误。

    • ycredentialPublicKey 中对应于 "-3" 键(表示 y 坐标)的值, 并确认其大小为 32 字节。如果大小不同或未找到 "-3" 键,终止此算法并返回 适当的错误。

    • publicKeyU2F 为连接 0x04 || x || y

      注意: 这表示未压缩的 ECC 公钥格式。

  5. verificationData 为连接(0x00 || rpIdHash || clientDataHash || credentialId || publicKeyU2F)(参见 第 4.3 节[FIDO-U2F-Message-Formats])。

  6. 使用 verificationDatacertificate public key 根据 [SEC1] 的第 4.1.4 节验证 sig, 使用 SHA-256 作为第二步中使用的哈希函数。

  7. 可选地,检查 x5c 并查阅外部提供的知识,确定 attStmt 是否传达了 基本AttCA 证明。

  8. 如果成功,返回表示 证明类型 基本AttCA 或不确定性,以及 证明信任路径 x5c

8.7. 无证明声明格式

无证明声明格式用于替换任何认证器提供的证明声明,当WebAuthn依赖方表示不希望接收证明信息时,参见§ 5.4.7 证明传递偏好枚举(enum AttestationConveyancePreference)

如果认证器不支持证明认证器也可以直接生成这种格式的证明声明。

证明声明格式标识符

none

支持的证明类型

语法

无证明声明的语法定义如下:

    $$attStmtType //= (
                          fmt: "none",
                          attStmt: emptyMap
                      )

    emptyMap = {}
签名过程

返回上面定义的固定证明声明。

验证过程

返回表示证明类型和空的证明信任路径的实现特定值。

8.8. 苹果匿名证明声明格式

此证明声明格式专为支持WebAuthn的某些类型的苹果设备使用。

证明声明格式标识符

apple

支持的证明类型

匿名CA

语法

苹果证明声明的语法定义如下:

    $$attStmtType //= (
                          fmt: "apple",
                          attStmt: appleStmtFormat
                      )

    appleStmtFormat = {
                          x5c: [ credCert: bytes, * (caCert: bytes) ]
                      }

上述字段的语义如下:

x5c

credCert后跟其证书链,每个都以X.509格式编码。

credCert

用于证明的凭证公钥证书,编码为X.509格式。

签名过程
  1. authenticatorData设为证明的认证器数据,并将clientDataHash设为序列化客户端数据的哈希

  2. 连接authenticatorDataclientDataHash以形成nonceToHash

  3. nonceToHash执行SHA-256哈希以生成nonce

  4. 让苹果匿名证明CA生成一个用于凭证公钥的X.509证书,并将nonce作为OID为1.2.840.113635.100.8.2的证书扩展名包含在内。credCert表示此证书。credCert因此作为证明的证明,并且包含的nonce证明证明是实时的。此外,nonce还保护了authenticatorData客户端数据的完整性。

  5. x5c设置为credCert及其证书链。

验证过程

给定验证过程输入attStmtauthenticatorDataclientDataHash,验证过程如下:

  1. 验证attStmt是符合上述语法定义的有效CBOR,并对其进行CBOR解码以提取包含的字段。

  2. 连接authenticatorDataclientDataHash以形成nonceToHash

  3. nonceToHash执行SHA-256哈希以生成nonce

  4. 验证nonce等于credCert中OID为1.2.840.113635.100.8.2的扩展名的值。

  5. 验证凭证公钥等于credCert的主题公钥。

  6. 如果成功,返回表示证明类型匿名CA和证明信任路径x5c的实现特定值。

9. WebAuthn扩展

生成公钥凭证以及请求和生成认证声明的机制,如§ 5 Web身份验证API中定义的,可以根据特定的用例进行扩展。每种情况都通过定义注册扩展和/或认证扩展来处理。

每个扩展都是一个客户端扩展,意味着该扩展涉及与客户端的通信和处理。客户端扩展定义了以下步骤和数据:

在创建公钥凭证或请求认证声明时,WebAuthn依赖方可以请求使用一组扩展。这些扩展将在请求的操作期间被调用,如果它们被客户端和/或WebAuthn认证器支持。依赖方get()调用中(用于认证扩展)或create()调用中(用于注册扩展)向客户端发送每个扩展的客户端扩展输入客户端为每个客户端平台支持的扩展执行客户端扩展处理,并按照每个扩展的规定通过包含扩展标识符客户端扩展输出值来扩展客户端数据

扩展还可以是一个认证器扩展,这意味着扩展涉及与认证器的通信和处理。认证器扩展定义了以下步骤和数据:

对于 身份验证器扩展,作为 客户端扩展处理 的一部分,客户端还为每个扩展创建 CBOR 身份验证器扩展输入 值 (通常基于相应的 客户端扩展输入 值),并将它们传递给身份验证器,在 create() 调用中(对于 注册扩展)或 get() 调用中(对于 身份验证扩展)。这些 身份验证器扩展输入 值以 CBOR 格式表示,并作为名称-值对传递,其中 扩展标识符 作为名称,相关的 身份验证器扩展输入 作为值。然后,身份验证器对其支持的扩展执行额外处理,并返回每个扩展的 CBOR 身份验证器扩展输出,如扩展所规定的那样。 作为 客户端扩展处理 的一部分,对于 身份验证器扩展,使用 身份验证器扩展输出 作为创建 客户端扩展输出 的输入。

所有 WebAuthn 扩展 对客户端和身份验证器都是可选的。因此,任何由 依赖方 请求的扩展,客户端浏览器或操作系统可以选择忽略,完全不传递给身份验证器,或者身份验证器也可以选择忽略这些扩展。 在 WebAuthn API 处理中,忽略扩展从不被视为失败,因此当 依赖方 在任何 API 调用中包含扩展时,他们必须准备好处理某些或所有扩展被忽略的情况。

希望支持最广泛扩展的客户端可以选择将它们无法识别的扩展传递给身份验证器,通过简单地将 客户端扩展输入 在 CBOR 中编码来生成 身份验证器扩展输入。所有 WebAuthn 扩展 必须以这样的方式定义,确保这种实现选择不会危及用户的安全或隐私。例如,如果一个扩展需要客户端处理,它可以被定义为确保这种简单的传递会产生一个语义无效的 身份验证器扩展输入 值,导致扩展 被身份验证器忽略。由于所有扩展都是可选的,这不会导致 API 操作中的功能失败。同样,客户端可以选择为它无法理解的扩展生成 客户端扩展输出 值,方法是将 身份验证器扩展输出 值编码为 JSON, 前提是 CBOR 输出只使用 JSON 中存在的类型。

客户端 选择将它们无法识别的扩展传递时,客户端扩展输入 中的 JavaScript 值被转换为 CBOR 值,并作为 身份验证器扩展输入 传递。 当 JavaScript 值是 %ArrayBuffer% 时,它被转换为 CBOR 字节数组。 当 JavaScript 值是非整数数字时,它会被转换为 64 位的 CBOR 浮点数。 否则,当 JavaScript 类型对应于 JSON 类型时,转换会按照 [RFC8949] 第 6.2 节中定义的规则进行(从 JSON 转换为 CBOR), 但是操作对象是 JavaScript 类型的输入值,而不是 JSON 类型的输入值。 完成这些转换后,必须使用 CTAP2 标准的 CBOR 编码格式 对结果的 CBOR 进行规范化。

请注意,JavaScript 的数值转换规则导致以下情况:当客户端传递一个它无法识别的扩展时,如果该扩展使用浮点值,认证器 需要准备好以 CBOR 整数的形式接收这些值,以确保如果 认证器 希望该扩展在没有实际 客户端 支持的情况下也能正常工作。当使用的浮点值恰好是整数时,就会发生这种情况。

同样,当客户端接收到它们通过的、未被识别的扩展输出时,CBOR值会在认证器扩展输出中转换为客户端扩展输出中的JavaScript值。当CBOR值是字节字符串时,它会被转换为JavaScript的%ArrayBuffer%(而不是base64url编码的字符串)。否则,当CBOR类型对应于JSON类型时,转换将按照[RFC8949]第6.1节(从CBOR到JSON的转换)中定义的规则进行,但生成的是JavaScript类型的值,而不是JSON类型的值。

请注意,一些客户端可能会选择在功能标志下实现这种透传能力。支持此功能可以促进创新,允许认证器在客户端明确支持之前,先行实验新的扩展,并允许依赖方使用它们。

IANA "WebAuthn扩展标识符"注册表[IANA-WebAuthn-Registries][RFC8809]建立,可以查询以获取注册的WebAuthn扩展的最新列表。

9.1. 扩展标识符

扩展通过一个字符串来标识,这个字符串称为扩展标识符,由扩展作者选择。

扩展标识符应注册在由[RFC8809]建立的IANA "WebAuthn扩展标识符"注册表中[IANA-WebAuthn-Registries]。所有注册的扩展标识符在它们之间是唯一的。

未注册的扩展标识符应尽量确保全局唯一,例如,通过包括定义实体如myCompany_extension

所有扩展标识符必须最长为32个八位字节,并且只能包含可打印的USASCII字符,排除反斜杠和双引号,即[RFC5234]中定义的VCHAR,但不包括%x22和%x5c。实现必须以区分大小写的方式匹配WebAuthn扩展标识符。

可能存在多个版本的扩展应注意在其标识符中包括一个版本。实际上,不同版本因此被视为不同的扩展,例如myCompany_extension_01

§ 10 定义的扩展定义了一组附加的扩展及其标识符。有关已注册WebAuthn扩展标识符的最新列表,请参阅IANA "WebAuthn扩展标识符"注册表[IANA-WebAuthn-Registries],由[RFC8809]建立。

9.2. 定义扩展

扩展的定义必须指定一个扩展标识符、一个发送至get()create() 调用的客户端扩展输入参数,客户端扩展处理规则,以及一个客户端扩展输出值。 如果扩展与认证器通信(即是认证器扩展), 则必须同时指定通过authenticatorGetAssertionauthenticatorMakeCredential调用发送的CBOR 认证器扩展输入参数, 认证器扩展处理规则,以及 CBOR 认证器扩展输出值。

任何由客户端处理的客户端扩展都必须返回一个客户端扩展输出值,以便WebAuthn 依赖方知道该扩展已被客户端认可。同样,任何需要认证器处理的扩展必须返回 一个认证器扩展输出,以便依赖方知道该 扩展已被认证器认可。如果扩展不需要任何结果值,则应定义为返回一个JSON布尔型客户端扩展 输出结果,设置为true以表示扩展已被理解并处理。 同样,任何不需要结果值的认证器扩展必须返回一个值,且应返回一个CBOR布尔型认证器扩展输出结果,设置为 true以表示扩展已被理解并处理。

9.3. 扩展请求参数

扩展定义了一个或两个请求参数。客户端扩展输入是一个可以编码为JSON的值,它从 WebAuthn 依赖方 传递到客户端,在 get()create() 调用中,而 CBOR 身份验证器扩展输入 是 在处理这些调用期间从客户端传递到身份验证器的,用于 身份验证器扩展

依赖方 同时请求使用扩展并设置其 客户端扩展输入,方法是在 extensions 选项中包含一个条目,传递给 create()get() 调用。条目键是 扩展标识符 ,值是 客户端扩展输入

注意: 其他文档已指定扩展,其中扩展输入并不总是使用 扩展标识符 作为条目键。 新的扩展应遵循上述约定。

var assertionPromise = navigator.credentials.get({
    publicKey: {
        // 其他成员为了简洁省略
        extensions: {
            // 标识"webauthnExample_foobar"扩展的“条目键”,
            // 其值是一个包含两个输入参数的映射:
            "webauthnExample_foobar": {
              foo: 42,
              bar: "barfoo"
            }
        }
    }
});

扩展定义必须指定其客户端扩展输入的有效值。客户端 应忽略具有无效客户端扩展输入的扩展。如果一个扩展不需要任何来自依赖方的参数,它应定义为接受一个布尔型客户端参数,设置为true,表示该扩展由依赖方请求。

仅影响客户端处理的扩展不需要指定身份验证器扩展输入。具有身份验证器处理的扩展必须指定如何从客户端扩展输入计算身份验证器扩展输入,并且必须通过定义额外的选择项来定义CDDL类型 AuthenticationExtensionsAuthenticatorInputsAuthenticationExtensionsAuthenticatorOutputs 通过使用扩展标识符作为条目键,定义$$extensionInput$$extensionOutput 组套接字。 不需要输入参数的扩展,因此定义为接受布尔型客户端扩展输入值设置为true,应将身份验证器扩展输入也定义为常量布尔值true(CBOR主类型7,值21)。

以下示例定义了一个扩展,其标识符webauthnExample_foobar,该扩展接受一个无符号整数作为身份验证器扩展输入, 并返回一个至少包含一个字节串的数组作为身份验证器扩展输出

$$extensionInput //= (
  webauthnExample_foobar: uint
)
$$extensionOutput //= (
  webauthnExample_foobar: [+ bytes]
)

注意: 扩展应尽量定义尽可能小的认证器参数。一些认证器通过低带宽的链接通信,如蓝牙低能量或NFC。

9.4. 客户端扩展处理

扩展可以在凭证创建或断言生成期间,对客户端定义附加处理要求。扩展的客户端扩展输入用作此客户端处理的输入。 对于每个支持的客户端扩展,客户端会向clientExtensions映射中添加一个条目,以扩展标识符作为键,并以扩展的客户端扩展输入作为值。

同样,客户端扩展输出getClientExtensionResults()的结果中表示为字典,以扩展标识符作为键,并以每个扩展的客户端扩展输出值作为值。 与客户端扩展输入类似,客户端扩展输出是可以编码为JSON的值。 忽略的扩展不应返回任何值。

需要认证器处理的扩展必须定义一种过程,该过程使用客户端扩展输入来确定CBOR认证器扩展输入的方式,以及通过CBOR认证器扩展输出来确定客户端扩展输出的方式。

9.5. 认证器扩展处理

每个已处理的认证器扩展CBOR认证器扩展输入值包含在extensions参数中,用于authenticatorMakeCredentialauthenticatorGetAssertion操作。extensions参数是一个CBOR映射,其中每个键是一个扩展标识符,相应的值是该扩展的认证器扩展输入

同样,扩展输出在扩展部分表示在认证器数据中。扩展部分的认证器数据是一个CBOR映射,其中每个键是一个扩展标识符,对应的值是该扩展的认证器扩展输出

对于每个支持的扩展,使用该扩展的 认证器扩展处理 规则,从 认证器扩展输入 以及可能的其他输入创建 认证器扩展输出。 对于被忽略的扩展,不得返回任何值。

10. 定义的扩展

本节定义了一组要在IANA "WebAuthn Extension Identifiers"注册表[IANA-WebAuthn-Registries]中注册的附加扩展,由[RFC8809]建立。 这些扩展可以由目标为广泛互操作性的用户代理实现。

10.1. FIDO AppID 扩展(appid)

该扩展允许先前使用传统FIDO U2F JavaScript API [FIDOU2FJavaScriptAPI]注册凭据的WebAuthn依赖方请求声明。 FIDO API使用替代标识符作为依赖方,称为AppID [FIDO-APPID],并且使用这些API创建的任何凭据将被限定到该标识符。 如果没有此扩展,它们将需要重新注册以便限定RP ID

除了设置appid 扩展输入外, 使用此扩展需要依赖方进行一些额外处理,以便允许用户使用其注册的U2F凭据进行身份验证

  1. allowCredentials 选项中列出所需的U2F凭据 在get() 方法中:

    • type 成员设置为public-key

    • id 成员设置为所需凭据的相应U2F密钥句柄。注意,U2F密钥句柄通常使用base64url编码,但在id中使用时必须解码为其二进制形式。

    allowCredentials 可以包含WebAuthn凭据ID和U2F密钥句柄的混合; 通过此扩展声明appid 并不妨碍用户使用注册到rpId中声明的RP ID的WebAuthn凭据。

  2. 验证声明时,期望rpIdHash可能是AppID的哈希值,而不是RP ID的哈希值。

此扩展不允许创建与FIDO兼容的凭据。因此, 使用WebAuthn创建的凭据不向后兼容FIDO JavaScript API。

注意: appid 应设置为依赖方 在传统FIDO API中先前使用的AppID。 这可能与将依赖方的WebAuthnRP ID转换为AppID格式的结果不同, 例如,以前使用的AppID可能是“https://accounts.example.com”, 但当前使用的RP ID可能是“example.com”。

扩展标识符

appid

操作适用性

身份验证

客户端扩展输入

指定FIDO AppID的单个USVString。

partial dictionary AuthenticationExtensionsClientInputs {
  USVString appid;
};
客户端扩展处理
  1. facetId成为将调用者的来源传递到 FIDO算法中以确定调用应用程序的FacetID的结果。

  2. appId成为扩展输入。

  3. facetIdappId传递给FIDO算法以确定调用者的FacetID是否获得AppID的授权。 如果该算法拒绝appId,则返回“SecurityErrorDOMException

  4. 构建allowCredentialDescriptorList时, 如果U2F认证器指示凭据不适用(即返回SW_WRONG_DATA),则客户端必须重试,将U2F应用参数设置为appId的SHA-256哈希。 如果这导致了一个适用的凭据,客户端必须将该凭据包含在allowCredentialDescriptorList中。 然后appId的值替换authenticatorGetAssertionrpId参数。

  5. output设置为布尔值false

  6. 创建assertionCreationData时, 如果声明由U2F认证器创建,并且U2F应用参数设置为appId的SHA-256哈希而不是RP ID的SHA-256哈希,则将output设置为true

注意: 实际上,几个实现没有执行算法的步骤四及以后的步骤确定调用者的FacetID是否获得AppID的授权。 相反,在步骤三中,主机上的比较放宽以接受同一站点上的主机。

客户端扩展输出

返回output的值。如果为true,则使用了AppID,因此,在验证声明时,依赖方必须期望rpIdHashAppID的哈希值,而不是RP ID

partial dictionary AuthenticationExtensionsClientOutputs {
  boolean appid;
};
认证器扩展输入

无。

认证器扩展处理

无。

认证器扩展输出

无。

10.2. FIDO AppID 排除扩展 (appidExclude)

此注册扩展允许WebAuthn 依赖方排除包含通过传统 FIDO U2F JavaScript API [FIDOU2FJavaScriptAPI] 创建的指定凭据的认证器。

在从 FIDO U2F JavaScript API 过渡期间,依赖方可能已经有一部分用户注册了传统凭据。appid扩展允许登录流程平稳过渡,但在过渡注册流程时,excludeCredentials字段在排除具有传统凭据的认证器方面不会有效,因为其内容被视为 WebAuthn 凭据。此扩展指示客户端平台excludeCredentials的内容视为 WebAuthn 和传统 FIDO 凭据。请注意,U2F 密钥句柄通常使用base64url 编码,但在excludeCredentials中使用时必须解码为其二进制形式。

扩展标识符

appidExclude

操作适用性

注册

客户端扩展输入

指定 FIDO AppID 的单个 USVString。

partial dictionary AuthenticationExtensionsClientInputs {
  USVString appidExclude;
};
客户端扩展处理

创建新凭据时:

  1. 建立 RP ID后立即执行以下步骤:

    1. facetId成为将调用者的来源传递给 FIDO 算法以确定调用应用程序的 FacetID 的结果。

    2. appId成为扩展输入的值appidExclude

    3. facetIdappId传递给 FIDO 算法,以确定调用者的 FacetID 是否获得 AppID 授权。如果后一个算法拒绝appId,则 返回 "SecurityError" DOMException 并终止创建新凭据算法以及这些步骤。

      注意: 实际上,几个实现没有执行算法的步骤四及以后的步骤确定调用者的 FacetID 是否获得 AppID 授权。相反,在第三步中,主机上的比较放宽为接受同一站点上的主机。

    4. 否则,继续正常处理。

  2. 调用 authenticatorMakeCredential之前执行以下步骤:

    1. 如果authenticator支持 U2F 协议[FIDO-U2F-Message-Formats],则针对每个 凭据描述符 CexcludeCredentialDescriptorList 中:

      1. 通过向authenticator发送一个U2F_AUTHENTICATE消息来检查C是否是使用authenticator上的 U2F 创建的,该消息的“5个部分”设置为以下值:

        控制字节

        0x07 ("check-only")

        挑战参数

        32 个随机字节

        应用参数

        appId 的 SHA-256 哈希

        密钥句柄长度

        C.id 的长度(以字节为单位)

        密钥句柄

        C.id 的值,即凭据 ID

      2. 如果authenticator响应message:error:test-of-user-presence-required(即成功),则停止对该authenticator的正常处理,并以平台特定的方式指示认证器不适用。例如,这可以以 UI 的形式显示,或可以涉及从authenticator请求用户同意,并在收到后,将其视为认证器已返回InvalidStateError。请求用户同意可以通过再次向authenticator发送U2F_AUTHENTICATE消息来实现,除了将控制字节设置为0x03 ("enforce-user-presence-and-sign") 并忽略响应。

    2. 继续正常处理。

客户端扩展输出

返回值true,以向依赖方指示已执行扩展。

partial dictionary AuthenticationExtensionsClientOutputs {
  boolean appidExclude;
};
认证器扩展输入

无。

认证器扩展处理

无。

认证器扩展输出

无。

10.3. 用户验证方法扩展 (uvm)

此扩展启用用户验证方法的使用。

扩展标识符

uvm

操作适用性

注册身份验证

客户端扩展输入

布尔值true,表示此扩展由依赖方请求。

partial dictionary AuthenticationExtensionsClientInputs {
  boolean uvm;
};
客户端扩展处理

无,除了从客户端扩展输入创建认证器扩展输入。

客户端扩展输出

返回一个包含 3 元素数组的 JSON 数组,这些数组编码了认证器扩展输出中的因素。

typedef sequence<unsigned long> UvmEntry;
typedef sequence<UvmEntry> UvmEntries;

partial dictionary AuthenticationExtensionsClientOutputs {
  UvmEntries uvm;
};
认证器扩展输入

布尔值true,以 CBOR 编码(主要类型 7,值 21)。

    $$extensionInput //= (
      uvm: true,
    )
认证器扩展处理

认证器认证器扩展输出设置为一个或多个用户验证方法,指示用户用于授权操作的方法,如下定义。此扩展可以添加到证明对象和断言中。

认证器扩展输出

认证器可以报告在单次身份验证实例中使用的最多 3 种不同的用户验证方法(因素),使用以下定义的 CBOR 语法:

    $$extensionOutput //= (
      uvm: [ 1*3 uvmEntry ],
    )

    uvmEntry = [
                   userVerificationMethod: uint .size 4,
                   keyProtectionType: uint .size 2,
                   matcherProtectionType: uint .size 2
               ]

每个uvmEntry中字段的语义如下:

userVerificationMethod

认证器用于验证用户的身份验证方法/因素。可用值在第 3.1 节 用户验证方法中定义[FIDO-Registry]

keyProtectionType

认证器用于保护 FIDO 注册私钥材料的方法。可用值在第 3.2 节 密钥保护类型中定义[FIDO-Registry]

matcherProtectionType

认证器用于保护执行用户验证的匹配器的方法。可用值在第 3.3 节 匹配器保护类型中定义[FIDO-Registry]

如果在一次身份验证实例中可以使用超过 3 种因素,认证器供应商必须选择其认为最相关的 3 种因素以包括在 UVM 中。

包含一个 UVM 扩展的认证器数据示例,适用于使用了 2 种因素的多因素身份验证实例:

...                    -- RP ID 哈希(32 字节)
81                     -- 设置了 UP 和 ED
00 00 00 01            -- (初始)签名计数器
...                    -- 所有公钥算法等。
A1                     -- 扩展:一个元素的 CBOR 映射
    63                 -- 键 1:3 字节的 CBOR 文本字符串
        75 76 6d       -- "uvm" [=UTF-8 编码=] 字符串
    82                 -- 值 1:长度为 2 的 CBOR 数组,表示使用了两种因素
        83              -- 项 1:长度为 3 的 CBOR 数组
            02           -- 子项 1:用于用户验证方法指纹的 CBOR 整数
            04           -- 子项 2:用于密钥保护类型 TEE 的 CBOR 短整数
            02           -- 子项 3:用于匹配器保护类型 TEE 的 CBOR 短整数
        83              -- 项 2:长度为 3 的 CBOR 数组
            04           -- 子项 1:用于用户验证方法密码的 CBOR 整数
            01           -- 子项 2:用于密钥保护类型软件的 CBOR 短整数
            01           -- 子项 3:用于匹配器保护类型软件的 CBOR 短整数

10.4. 凭据属性扩展 (credProps)

客户端注册扩展有助于在注册仪式的结果中创建公钥凭据源时,将客户端已知的某些凭据属性报告给请求的WebAuthn 依赖方

目前,定义了一种凭据属性驻留密钥凭据属性(即客户端可发现的凭据属性)。

扩展标识符

credProps

操作适用性

注册

客户端扩展输入

布尔值true,表示此扩展由依赖方请求。

partial dictionary AuthenticationExtensionsClientInputs {
    boolean credProps;
};
客户端扩展处理

无,除了在输出中报告凭据属性。

客户端扩展输出

设置 clientExtensionResults["credProps"]["rk"] 为在 调用authenticatorMakeCredential 操作中使用的 requireResidentKey 参数的值。

dictionary CredentialPropertiesOutput {
    boolean rk;
};

partial dictionary AuthenticationExtensionsClientOutputs {
    CredentialPropertiesOutput credProps;
};
rk, 类型 boolean

此可选属性,抽象地称为驻留密钥凭据属性(即客户端可发现的凭据属性), 是一个布尔值,指示是否注册仪式的结果是 PublicKeyCredential客户端可发现的凭据。 如果rktrue,则凭据是可发现的凭据。 如果rkfalse,则凭据是服务器端凭据。 如果rk没有出现,则不确定该凭据是可发现的凭据还是服务器端凭据

注意:有些认证器即使在未被客户端平台请求的情况下,也会创建可发现的凭据。因此,客户端平台可能被迫省略rk属性,因为他们缺乏设置为false的保证。依赖方应该假定,如果支持credProps扩展,则客户端平台将努力填充rk属性。因此,缺少rk表示创建的凭据很可能是不可发现的凭据

认证器扩展输入

无。

认证器扩展处理

无。

认证器扩展输出

无。

10.5. 大数据块存储扩展 (largeBlob)

客户端注册扩展身份验证扩展允许依赖方存储与凭据关联的不透明数据。由于认证器只能存储少量数据,而大多数依赖方是可以为用户存储任意状态的在线服务,这仅在特定情况下有用。例如,依赖方可能希望颁发证书,而不是运行集中式身份验证服务。

注意:依赖方可以假设在写入空间有限的设备时,不透明数据将被压缩,因此无需自行压缩。

由于证书系统需要签署凭据的公钥,而该公钥仅在创建后可用,因此此扩展不会增加在注册上下文中写入数据块的能力。然而,如果依赖方希望稍后使用身份验证扩展依赖方应在创建凭据时使用注册扩展

由于证书相对于典型认证器的存储能力较大,用户代理应考虑合适的指示和确认,以最好地指导用户分配这一有限资源并防止滥用。

注意:为了实现互操作性,用户代理在使用[FIDO-CTAP]的认证器上存储大数据块时,应使用该规范中详细说明的用于存储大数据块的条款。

扩展标识符

largeBlob

操作适用性

注册身份验证

客户端扩展输入
partial dictionary AuthenticationExtensionsClientInputs {
    AuthenticationExtensionsLargeBlobInputs largeBlob;
};

enum LargeBlobSupport {
  "required",
  "preferred",
};

dictionary AuthenticationExtensionsLargeBlobInputs {
    DOMString support;
    boolean read;
    BufferSource write;
};
support, 类型 DOMString

一个 DOMString,取LargeBlobSupport的值之一。 (参见§ 2.1.1 DOMString 类型的枚举。)仅在注册期间有效。

read, 类型 boolean

一个布尔值,指示依赖方希望获取与断言的凭据关联的先前写入的数据块。仅在身份验证期间有效。

write, 类型 BufferSource

一个依赖方希望与现有凭据一起存储的不透明字节串。仅在身份验证期间有效。

客户端扩展处理 (注册)
  1. 如果存在readwrite

    1. 返回一个DOMException ,其名称为“NotSupportedError”。

  2. 如果存在support 并且其值为required

    1. supported 设置为true

      注意:这是为了预期能够存储大块数据的身份验证器的可用性。在[[Create]]()的步骤11中发生扩展处理。如果没有满足要求的身份验证器可用,则AuthenticationExtensionsLargeBlobOutputs 将被放弃。

    2. 如果在步骤19中可用一个候选身份验证器[[Create]]()), 然后在评估任何options之前,继续(即忽略候选身份验证器),如果该候选身份验证器不支持存储大块数据。

  3. 否则(即support 缺失或其值为preferred):

    1. 如果选择了身份验证器,并且 所选身份验证器支持 大块数据,则将supported 设置为true,否则设置为false

客户端扩展处理 (身份验证)
  1. 如果support存在:

    1. 返回一个DOMException,其名称为“NotSupportedError”。

  2. 如果readwrite都存在:

    1. 返回一个DOMException,其名称为“NotSupportedError”。

  3. 如果read存在且值为true

    1. 初始化客户端扩展输出largeBlob

    2. 如果任何认证器指示成功(在[[DiscoverFromExternalSource]]()),尝试读取与断言的凭据关联的任何largeBlob数据。

    3. 如果成功,将blob设置为结果。

      注意:如果读取不成功,largeBlob将在AuthenticationExtensionsClientOutputs中存在,但blob成员将不存在。

  4. 如果write存在:

    1. 如果allowCredentials不包含完全一项:

      1. 返回一个DOMException,其名称为“NotSupportedError”。

    2. 如果断言操作成功,尝试将write的内容存储在认证器上,与指定的凭据关联。

    3. 如果成功,将written设置为true,否则设置为false

客户端扩展输出
partial dictionary AuthenticationExtensionsClientOutputs {
    AuthenticationExtensionsLargeBlobOutputs largeBlob;
};

dictionary AuthenticationExtensionsLargeBlobOutputs {
    boolean supported;
    ArrayBuffer blob;
    boolean written;
};
supported, 类型 boolean

如果且仅当创建的凭据支持存储大数据块时,true。仅在注册输出中存在。

blob, 类型 ArrayBuffer

rawId标识的凭据关联的不透明字节串。仅当readtrue时有效。

written, 类型 boolean

指示write的内容是否已成功存储在与指定凭据关联的认证器上的布尔值。

认证器扩展处理

此扩展指示用户代理将大数据块存储在认证器上或从认证器中检索,因此它不会为依赖方指定任何直接的认证器交互。

11. 用户代理自动化

为了用户代理自动化和web应用程序测试,本文件定义了一些[WebDriver] 扩展命令

11.1. WebAuthn WebDriver 扩展功能

为了宣传下面定义的扩展命令的可用性,定义了一个新的扩展功能

功能 值类型 描述
虚拟认证器支持 "webauthn:virtualAuthenticators" boolean 指示端点节点是否支持所有虚拟认证器命令。

验证功能时,验证"webauthn:virtualAuthenticators"value的特定扩展步骤如下:

  1. 如果value不是boolean,返回WebDriver错误,并附带WebDriver错误代码 无效参数

  2. 否则,将deserialized设置为value

匹配功能时,匹配"webauthn:virtualAuthenticators"value的特定扩展步骤如下:

  1. 如果valuetrue,且端点节点不支持任何虚拟认证器命令,则匹配不成功。

  2. 否则,匹配成功。

11.1.1. 认证器扩展功能

此外,本规范中定义的每个认证器扩展(即定义了认证器扩展处理的扩展)都有其相应的扩展能力定义:

功能 值类型 描述
用户验证方法扩展支持 "webauthn:extension:uvm" boolean 指示端点节点 WebAuthn WebDriver实现是否支持用户验证方法扩展。
大数据存储扩展支持 "webauthn:extension:largeBlob" boolean 指示端点节点 WebAuthn WebDriver实现是否支持largeBlob 扩展。

验证功能时,验证认证器扩展功能keyvalue的特定扩展步骤如下:

  1. 如果value不是boolean,返回WebDriver错误,并附带WebDriver错误代码 无效参数

  2. 否则,将deserialized设置为value

匹配 功能时,匹配认证器扩展功能keyvalue的特定扩展步骤如下:

  1. 如果valuetrue,且端点节点 WebAuthn WebDriver实现不支持key标识的认证器扩展,则匹配不成功。

  2. 否则,匹配成功。

实现定义的认证器扩展的用户代理应实现相应的认证器扩展功能

11.2. 虚拟验证器

这些WebDriver 扩展命令 用来创建和交互 虚拟验证器验证器模型 的软件实现。虚拟验证器 存储在 虚拟验证器数据库 中。 每个存储的虚拟验证器 具有以下属性:

验证器ID

使用 [RFC3986] 附录A中定义的最多48个字符组成的非空字符串,用于唯一标识虚拟验证器

protocol

虚拟验证器 支持的协议之一:"ctap1/u2f", "ctap2""ctap2_1" [FIDO-CTAP]

transport

模拟的 验证器传输。如果 transport 设置为 内部, 则验证器模拟 平台附件。否则,它将模拟 跨平台附件

hasResidentKey

如果设置为true,则验证器将支持客户端可发现凭据

hasUserVerification

如果设置为true,则验证器支持用户验证

isUserConsenting

决定所有用户同意 授权手势的结果, 并扩展到在 虚拟验证器 上执行的任何 用户存在测试。如果设置为 true用户同意 将始终被授予。如果设置为 false,则不会授予。

isUserVerified

决定在 虚拟验证器 上执行的 用户验证 的结果。如果设置为true用户验证 将始终成功。如果设置为 false,则会失败。

注意:如果 hasUserVerification 设置为false,此属性将无效。

extensions

包含 扩展标识符 的字符串数组,支持 虚拟验证器

一个虚拟验证器 必须支持其 extensions 数组中的所有 验证器扩展。 它不能支持任何 不在其extensions数组中存在的验证器扩展

uvm

当处理 用户验证方法扩展时,设置为 验证器扩展输出UvmEntries数组。

注意:如果 虚拟验证器 不支持 用户验证方法扩展,则此属性无效。

11.3. 添加虚拟验证器

添加虚拟验证器 WebDriver 扩展命令 创建一个软件 虚拟验证器。其定义如下:

HTTP 方法 URI 模板
POST /session/{session id}/webauthn/authenticator

验证器配置 是一个 JSON 对象,通过 远程端步骤 作为参数传递。它包含以下 对:

值类型 有效值 默认值
protocol 字符串 "ctap1/u2f", "ctap2", "ctap2_1"
transport 字符串 验证器传输
hasResidentKey 布尔值 true, false false
hasUserVerification 布尔值 true, false false
isUserConsenting 布尔值 true, false true
isUserVerified 布尔值 true, false false
extensions 字符串数组 包含 扩展标识符 的数组 空数组
uvm UvmEntries 最多包含3个 用户验证方法 条目 空数组

远程端步骤 如下:

  1. 如果 parameters 不是 JSON 对象,返回一个 WebDriver 错误,错误代码为 WebDriver 错误代码 无效参数

    注意: parameters 是一个 验证器配置 对象。

  2. authenticator 为新的 虚拟验证器

  3. 对于 parameters 中的每个可枚举 自有属性

    1. key 为属性名称。

    2. value获取属性 parameters 中名为 key 的属性的结果。

    3. 如果 parameters 中没有与 key 匹配的 key,返回 WebDriver 错误,错误代码为 WebDriver 错误代码 无效参数

    4. 如果 value 不是该 key有效值 之一,返回 WebDriver 错误,错误代码为 WebDriver 错误代码 无效参数

    5. 设置属性 keyauthenticator 上的 value

  4. 对于 验证器配置 中定义了默认值的每个属性:

    1. 如果 authenticator 没有定义的 key 属性,设置属性 keyauthenticator 上的 default

  5. 对于 验证器配置 中的每个属性:

    1. 如果 authenticator 没有定义的 key 属性,返回 WebDriver 错误,错误代码为 WebDriver 错误代码 无效参数

  6. 对于 authenticator.extensions 中的每个 extension

    1. 如果 extension 不是由 扩展标识符 支持的 端点节点 WebAuthn WebDriver 实现,返回 WebDriver 错误,错误代码为 WebDriver 错误代码 不支持的操作

  7. 生成有效唯一的 authenticatorId

  8. 设置属性 authenticatorIdauthenticator 上的 authenticatorId

  9. authenticator 存储在 虚拟验证器数据库 中。

  10. 返回 成功,数据为 authenticatorId

11.4. 移除虚拟验证器

移除虚拟验证器 WebDriver 扩展命令 移除先前创建的 虚拟验证器。 定义如下:

HTTP 方法 URI 模板
DELETE /session/{session id}/webauthn/authenticator/{authenticatorId}

远程端步骤如下:

  1. 如果 authenticatorId 与存储在 虚拟认证器 数据库中的任何 虚拟认证器数据库 不匹配,则返回一个带有 WebDriver 错误WebDriver 错误代码,错误类型为 无效参数

  2. 虚拟认证器 中移除由 authenticatorId 标识的 虚拟认证器数据库

  3. 返回 成功

11.5. 添加凭证

添加凭证 WebDriver 扩展命令公钥凭证来源 注入到现有的 虚拟验证器中。定义如下:

HTTP 方法 URI 模板
POST /session/{session id}/webauthn/authenticator/{authenticatorId}/credential

凭证参数 是一个 JSON 对象,作为 parameters 传递给 远程端步骤。它包含以下 keyvalue 对:

描述 值类型
credentialId 使用Base64url编码凭证ID字符串
isResidentCredential 如果设置为true,则创建一个客户端可发现凭证。如果设置为false,则创建一个服务器端凭证布尔值
rpId 凭证的范围依赖方ID字符串
privateKey 每个[RFC5958]包含的单个私钥的非对称密钥包,使用Base64url编码字符串
userHandle 与凭证关联的userHandle,使用Base64url编码。此属性可能未定义。 字符串
signCount 公钥凭证源关联的签名计数器的初始值。 数字
largeBlob 公钥凭证源关联的大型,每凭证的blob,使用Base64url编码。 此属性可能未定义。 字符串

远程端步骤如下:

  1. 如果 parameters 不是 JSON 对象, 返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

    注意: parameters 是一个 凭证参数 对象。

  2. credentialId 成为使用 Base64url 编码parameterscredentialId 属性进行解码的结果。

  3. 如果 credentialId 解码失败,返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

  4. isResidentCredential 成为 parametersisResidentCredential 属性。

  5. 如果 isResidentCredential 未定义,返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

  6. rpId 成为 parametersrpId 属性。

  7. 如果 rpId 不是有效的 RP ID, 返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

  8. privateKey 成为使用 Base64url 编码parametersprivateKey 属性进行解码的结果。

  9. 如果 privateKey 解码失败,返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

  10. 如果 privateKey 不是包含单个 ECDSA 私钥的有效编码的非对称密钥包,符合 [RFC5958] 的 P-256 曲线标准, 返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

  11. 如果 parametersuserHandle 属性已定义:

    1. userHandle 成为使用 Base64url 编码parametersuserHandle 属性进行解码的结果。

    2. 如果 userHandle 解码失败,返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

  12. 否则:

    1. 如果 isResidentCredentialtrue,返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

    2. userHandlenull

  13. 如果authenticatorId虚拟认证器数据库中存储的任何虚拟认证器数据库中的虚拟认证器不匹配,则返回带有WebDriver错误WebDriver错误代码 无效参数

  14. authenticator 成为与 authenticatorId 匹配的 虚拟验证器

  15. 如果 isResidentCredentialtrue,且 authenticatorhasResidentKey 属性为 false, 返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

  16. 如果 authenticator 支持 largeBlob 扩展,并且 parameterslargeBlob 特性已定义:

    1. largeBlob 成为使用 Base64url 编码parameterslargeBlob 属性进行解码的结果。

    2. 如果 largeBlob 解码失败,返回 WebDriver 错误, 并附带 WebDriver 错误代码 无效参数

  17. 否则:

    1. largeBlobnull

  18. credential 成为一个新的 客户端可发现的公钥凭证来源, 如果 isResidentCredentialtrue,否则让其成为 服务器端公钥凭证来源, 其项包括:

    类型

    public-key

    id

    credentialId

    privateKey

    privateKey

    rpId

    rpId

    userHandle

    userHandle

  19. 将一个与 credential 关联的 签名计数器 counter, 其初始值等于 parameterssignCount, 如果 signCountnull,则默认为 0

  20. 如果 largeBlob 不为 null, 将与 credential 关联的 大块 blob 设置为 largeBlob

  21. credentialcounter 存储在 authenticator 的数据库中。

  22. 返回 成功

11.6. 获取凭证

获取凭证的WebDriver扩展命令为每个存储在虚拟认证器中的公钥凭证源返回一个凭证参数对象,无论它们是使用添加凭证还是navigator.credentials.create()存储的。定义如下:

HTTP 方法 URI 模板
GET /session/{session id}/webauthn/authenticator/{authenticatorId}/credentials

远程端步骤如下:

  1. 如果 authenticatorId 与存储在 虚拟身份验证器 中的任何 虚拟身份验证器数据库 不匹配,返回一个 WebDriver 错误,错误代码为 WebDriver 错误代码 无效参数

  2. credentialsArray 为一个空数组。

  3. 对于每个由 authenticatorId 标识的身份验证器管理的 公钥凭证源 credential,构造一个对应的 凭证参数 对象并将其添加到 credentialsArray 中。

  4. 返回 成功,数据包含 credentialsArray

11.7. 移除凭证

移除凭证 WebDriver 扩展命令 移除存储在 虚拟验证器上的公钥凭证来源。定义如下:

HTTP 方法 URI 模板
DELETE /session/{session id}/webauthn/authenticator/{authenticatorId}/credentials/{credentialId}

远程端步骤如下:

  1. 如果 authenticatorId 不匹配任何存储在 虚拟身份验证器虚拟身份验证器数据库,返回一个 WebDriver 错误,其 WebDriver 错误代码无效参数

  2. authenticator 为由 authenticatorId 标识的 虚拟身份验证器

  3. 如果 credentialId 不匹配由 authenticator 管理的任何 公钥凭证源,返回一个 WebDriver 错误,其 WebDriver 错误代码无效参数

  4. 移除由 credentialId 标识的、由 authenticator 管理的 公钥凭证源

  5. 返回 成功

11.8. 移除所有凭证

移除所有凭证 WebDriver 扩展命令 移除存储在 虚拟验证器上的所有公钥凭证来源。定义如下:

HTTP 方法 URI 模板
DELETE /session/{session id}/webauthn/authenticator/{authenticatorId}/credentials

远程端步骤如下:

  1. 如果 authenticatorId虚拟认证器虚拟认证器数据库 中没有匹配项,则返回一个 WebDriver 错误,并带有 WebDriver 错误代码 无效参数

  2. 移除由 虚拟认证器 管理的所有 公钥凭证源,该虚拟认证器由 authenticatorId 标识。

  3. 返回 成功

11.9. 设置用户已验证

设置用户已验证 扩展命令 设置虚拟验证器上的 isUserVerified 属性。定义如下:

HTTP 方法 URI 模板
POST /session/{session id}/webauthn/authenticator/{authenticatorId}/uv

远程端步骤如下:

  1. 如果 parameters 不是一个 JSON 对象,返回一个 WebDriver 错误 ,错误码为 WebDriver 错误码 无效参数

  2. 如果 authenticatorId 与存储在 虚拟身份验证器 中的任何 虚拟身份验证器数据库 不匹配,返回一个 WebDriver 错误,错误码为 WebDriver 错误码 无效参数

  3. 如果 isUserVerified 不是 parameters 的定义属性,返回一个 WebDriver 错误,错误码为 WebDriver 错误码 无效参数

  4. authenticator 为由 authenticatorId 标识的 虚拟身份验证器

  5. authenticatorisUserVerified 属性设置为 parameters 中的 isUserVerified 属性。

  6. 返回 成功

12. IANA 考虑

12.1. WebAuthn Attestation 声明格式标识符注册更新

本节更新了在 IANA "WebAuthn Attestation 声明格式标识符" 注册表中定义的以下列举的声明格式(详见§ 8 定义的声明格式),并指向此规范。此注册表由 [RFC8809] 创建,最初注册于 [WebAuthn-1]

12.2. WebAuthn Attestation 声明格式标识符注册

本节在 IANA "WebAuthn Attestation 声明格式标识符" 注册表中注册以下列举的声明格式,这些格式在 § 8 定义的声明格式 中新定义,由 [RFC8809] 创建。

12.3. WebAuthn 扩展标识符注册更新

本节更新了 IANA "WebAuthn 扩展标识符" 注册表中定义的以下列举的 扩展标识符 值(详见 § 10 定义的扩展), 该注册表由 [RFC8809] 创建,最初注册于 [WebAuthn-1],并指向本规范。

12.4. WebAuthn 扩展标识符注册

本节在 IANA "WebAuthn 扩展标识符" 注册表中注册以下列举的 扩展标识符 值,这些值在 § 10 定义的扩展 中新定义,由 [RFC8809] 创建。

13.安全考虑

本规范定义了一种Web API和一种加密的对等实体身份验证协议。Web身份验证API允许Web开发者(即“作者”)在其注册身份验证仪式中利用Web身份验证协议。构成Web身份验证协议端点的实体是用户控制的WebAuthn身份验证器和承载依赖方Web应用程序WebAuthn依赖方计算环境。在此模型中,用户代理与WebAuthn客户端共同构成了身份验证器依赖方之间的中介。此外,身份验证器可以证明其来源,以供依赖方使用。

目前,本规范未包含详细的安全考虑。然而,[FIDOSecRef]文档提供了总体适用于本规范的安全分析。此外,[FIDOAuthnrSecReqs]文档系列提供了关于身份验证器安全特性的有用信息。

以下小节包含当前Web身份验证特定的安全考虑。它们按受众划分;一般安全考虑是本节的直接小节,而专门针对身份验证器客户端依赖方实现者的安全考虑则分组到相应的小节中。

13.1.凭证ID未签名

凭证ID未被签名。这并不是问题,因为如果身份验证器返回错误的凭证ID,或者如果攻击者拦截并操纵凭证ID,唯一的结果是WebAuthn依赖方将无法查找正确的凭证公钥来验证返回的签名身份验证器数据(即断言),因此交互将以错误结束。

13.2. 客户端与认证器之间的物理接近性

在 WebAuthn 认证器模型中,通常假设 漫游认证器客户端 物理接近,并直接与客户端通信。 这种安排有一些重要的优势。

客户端 client认证器 之间物理接近的承诺是 拥有某物 认证因素 的关键优势之一。 例如,如果一个 漫游认证器 只能通过 USB 或蓝牙通信, 这些传输方式的有限范围确保了任何恶意行为者必须物理上处于该范围内才能与 认证器 互动。 但对于可以远程调用的 认证器 来说,这并不一定成立 — 即使 认证器 验证了 用户在场, 用户仍可能被诱骗授权远程发起的恶意请求。

客户端认证器之间的直接通信意味着客户端可以执行对范围限制的管理,以控制凭证的访问。相反,如果客户端认证器之间的通信由第三方介导,则客户端必须信任该第三方来执行范围限制并控制对认证器的访问。未能做到任何一项可能导致恶意的依赖方获得对其他依赖方有效的认证声明,或恶意用户获得其他用户的认证声明

如果设计一个解决方案,其中认证器不需要与客户端物理接近,或者客户端认证器不直接通信,则设计者应考虑这种情况如何影响范围限制的执行以及作为拥有物认证因素的认证器的强度。

13.3. 关于认证器的安全考虑

13.3.1. 证明书证书层级

推荐使用三层证明书证书层级(即证明书根、证明书颁发CA、证明书证书)。同样推荐的是,对于每个WebAuthn验证器设备线(即型号),使用单独的颁发CA,以帮助隔离特定版本验证器型号的问题。

如果证明书根证书并未专用于某一WebAuthn验证器设备线(即AAGUID),则应在证明书证书本身中指定AAGUID,以便可以对照验证器数据进行验证。

13.3.2. 证明书证书和证明书证书CA泄露

当用于颁发认证证书的中间CA或根CA被破坏时,WebAuthn认证器认证密钥对仍然是安全的,尽管它们的证书不再可信。已记录其认证器型号的认证公钥WebAuthn认证器制造商可以为这些密钥颁发新的认证证书,该证书由新的中间CA或新的根CA签发。如果根CA发生变化,WebAuthn依赖方必须相应更新其受信任的根证书。

如果 私钥 已被泄露,则颁发 CA 必须撤销 WebAuthn 认证器认证证书。如果泄露是由固件缺陷引起的,WebAuthn 认证器制造商可能需要发布固件更新并将新的 认证私钥认证证书 注入到已制造的 WebAuthn 认证器 中。(此过程不在本规范的范围内。)如果 WebAuthn 认证器 制造商没有此能力,则 依赖方 可能无法信任来自受影响的 WebAuthn 认证器 的任何后续 认证声明

另请参见依赖方§ 13.4.5 被吊销的证明书证书中的相关安全性考虑。

13.4. 依赖方的安全性考虑

13.4.1. WebAuthn依赖方的安全性优势

本规范为WebAuthn依赖方提供的主要优势包括:

  1. 用户和账户可以通过广泛兼容、易于使用的多因素身份验证来保护。

  2. 依赖方不需要向其用户提供验证器硬件。相反,每个用户可以独立获取任何符合要求的验证器,并将该验证器与任意数量的依赖方一起使用。依赖方可以选择通过检查由验证器返回的证明书声明,强制执行对验证器安全特性的要求。

  3. 身份验证流程中间人攻击具有抵抗力。关于注册流程,请参见下面的§ 13.4.4 证明书限制

  4. 依赖方可以自动支持多种用户验证方法,例如PIN码、生物识别和/或未来的方法,且几乎无需修改代码,并可以通过用户选择的验证器让每个用户决定他们更愿意使用哪种方法。

  5. 依赖方不需要存储额外的秘密信息即可获得上述优势。

一致性部分所述,依赖方必须按照§ 7 WebAuthn依赖方操作中描述的方式行事,以获得上述所有安全性优势。然而,下面描述的一个显著用例略有不同,见§ 13.4.4 证明书限制

13.4.2. 嵌入式使用的可见性考虑

在嵌入式环境中简化使用 WebAuthn,例如在 iframe 中,正如 § 5.10 在 iframe 元素中使用 Web 身份验证 中所述,可能使用户容易受到 UI 重定向 攻击,也称为 "点击劫持"。这是指攻击者将自己的 UI 叠加在 依赖方 预期的 UI 上,并试图诱使用户与 依赖方 执行未预期的操作。例如,使用这些技术,攻击者可能能够诱使用户购买物品、转账等。

尽管WebAuthn特定的UI通常由客户端平台处理,因此不容易受到UI重定向的影响,但对于嵌入WebAuthn内容的依赖方来说,确保其内容的UI对用户可见可能非常重要。一种新兴的方法是观察实验性交叉观察者v2isVisible属性的状态。例如,嵌入式环境中运行的依赖方脚本可以在检测到isVisble被设置为false时预先加载自己到弹出窗口中,从而绕过其内容的遮挡。

13.4.3. 加密挑战

作为一种加密协议,Web身份验证依赖随机挑战来避免重放攻击。因此,PublicKeyCredentialCreationOptions.challengePublicKeyCredentialRequestOptions.challenge的值必须由依赖方在其信任的环境中(例如在服务器端)随机生成,并且客户端响应中的返回challenge值必须与生成的值匹配。这应该以不依赖于客户端行为的方式进行,例如,依赖方应暂时存储挑战,直到操作完成。容忍不匹配会损害协议的安全性。

为了防止重放攻击,挑战必须包含足够的熵以使猜测它们变得不可行。因此,挑战应至少为16个字节长。

13.4.4. 认证声明的限制

本节不是规范性的。

注册新凭证时,如果存在,认证声明 可能允许 WebAuthn 依赖方 推断出关于各种认证器的特性。 例如,认证器的模型,或者它如何存储和保护凭证私钥。 然而,需要注意的是,仅凭认证声明本身,依赖方无法验证认证声明对象是否由用户期望的认证器生成,而非由中间人攻击者生成。 例如,攻击者可以利用注入到依赖方脚本中的恶意代码。 因此,依赖方 必须依赖其他手段,例如 TLS 和相关技术,来保护认证声明对象免受中间人 攻击

假设注册仪式已安全完成,并且认证器保持了凭证私钥的机密性,那么使用该公钥凭证 的后续认证仪式能够抵御中间人 攻击

上述讨论适用于所有证明类型。在所有情况下,都有可能存在一个中间人攻击者替换PublicKeyCredential对象,包括需要注册的证明声明凭证公钥,并随后篡改未来为相同依赖方和通过相同攻击者传递的身份验证声明范围

这种攻击有可能被发现;因为依赖方已经注册了攻击者的凭证公钥,而不是用户的, 攻击者必须篡改所有与该依赖方相关的后续认证仪式: 无害的仪式将会失败,可能揭示攻击行为。

认证类型,除了自我认证外,可以增加此类攻击的难度,因为依赖方可以显示认证器信息,例如型号名称。 因此,攻击者可能需要使用与用户的认证器相同型号的真正认证器,或者用户可能会注意到,依赖方报告的认证器型号与用户预期的不同。

注意:上述所有形式的中间人攻击对攻击者来说要比针对传统密码认证的中间人攻击更难实施。

13.4.5. 被吊销的证明书证书

如果证明书证书验证因中间证明书CA证书被吊销而失败,并且依赖方的策略要求在这种情况下拒绝注册/身份验证请求,则建议依赖方还应取消注册(或将其信任级别标记为等同于“自我证明”)在CA泄露日期后使用与同一中间CA链接的证明书证书注册的公钥凭证。因此,建议依赖方注册期间记住中间证明书CA证书,以便在吊销此类证书后取消注册相关的公钥凭证,如果该注册是在吊销此类证书后进行的。

另请参见验证器§ 13.3.2 证明书证书和证明书证书CA泄露中的相关安全性考虑。

13.4.6. 凭证丢失与密钥移动性

本规范未定义用于备份 凭证私钥 或在 身份验证器 之间共享它们的协议。一般来说,预计 凭证私钥 永远不会离开创建它的 身份验证器。因此,丢失一个 身份验证器,通常意味着丢失所有与丢失的 身份验证器 绑定的 凭证,这可能会导致用户无法访问账户,尤其是当用户仅在 依赖方 注册了一个 凭证 时。Web 身份验证 API 不通过备份或共享私钥来解决此问题,而是允许为同一用户注册多个 凭证。例如,用户可以在常用的 客户端设备 上注册 平台凭证,并为备份和新设备或不常用的 客户端设备 注册一个或多个 漫游凭证,以及为丢失的 绑定凭证 提供备份。

依赖方 应该允许并鼓励用户为同一账户注册多个 凭证依赖方 应该使用 excludeCredentialsuser.id 选项来确保这些不同的 凭证绑定 到不同的 身份验证器

13.4.7. 未保护账户检测

本节不是规范性内容。

此安全考虑适用于支持具有非 allowCredentials 参数作为第一步身份验证的 Relying Parties。例如,如果使用 身份验证仪式服务器端凭证 作为第一步身份验证。

在这种情况下,allowCredentials参数有泄露信息的风险,关于哪些用户帐户已注册WebAuthn凭证,哪些没有,这可能是帐户保护强度的信号。例如,假设攻击者仅通过提供用户名即可发起身份验证仪式,并且依赖方对此作出响应,某些用户返回非空的allowCredentials,而其他用户则返回失败或密码挑战。攻击者可以得出结论,后者用户帐户可能不需要WebAuthn断言进行成功身份验证,因此集中攻击那些可能较弱的帐户。

这个问题类似于§ 14.6.2 用户名枚举§ 14.6.3 通过凭证ID的隐私泄漏中描述的问题,并可以通过类似的方式进行缓解。

14. 隐私注意事项

[FIDO-Privacy-Principles]》中的隐私原则同样适用于本规范。

本节按受众分为几部分;一般隐私注意事项直接作为本节的子节,而专门针对认证器客户端依赖方实现者的隐私注意事项则分组到各自的子节中。

14.1. 防止去匿名化的措施

本节不具备规范性。

Web Authentication API》设计中的许多方面都是出于隐私考虑。 本规范中考虑的主要问题是保护用户的个人身份,即识别一个人或将不同的身份关联为属于同一人的问题。虽然《Web Authentication API》不使用或提供任何形式的全球身份标识,但使用了以下几种可能相关的标识符:

上述部分信息是必然会与依赖方共享的。以下章节描述了为防止恶意依赖方利用这些信息来发现用户的个人身份而采取的措施。

14.2. 匿名的、作用域限定的、不可关联的公钥凭证

本节不具备规范性。

尽管凭证ID凭证公钥为了实现强身份验证,必须与WebAuthn依赖方共享,但它们被设计为最小化识别性,且不会在依赖方之间共享。

此外,客户端可发现的公钥凭证源可以选择性地包括由依赖方指定的用户句柄凭证然后可以用于同时标识和验证用户。这意味着隐私意识强的依赖方可以允许用户在没有传统用户名的情况下创建账户,从而进一步提高依赖方之间的不可关联性。

14.3. 认证器本地的生物识别

生物识别认证器认证器内部执行生物识别——但对于平台认证器,生物识别数据可能也对客户端可见,具体取决于实现方式。生物识别数据不会泄露给WebAuthn依赖方;它仅在本地用于执行用户验证,授权创建和注册或使用认证公钥凭证。因此,恶意的依赖方无法通过生物识别数据发现用户的个人身份,并且在依赖方发生的安全漏洞也不会暴露生物识别数据,供攻击者用于伪造其他依赖方的登录。

如果依赖方要求生物识别,此操作将由执行用户验证生物识别认证器在本地执行,然后通过在签名的断言响应中设置UV标志来传递结果,而不是将生物识别数据本身泄露给依赖方

14.4. 认证器的隐私考虑

14.4.1. 证明隐私

证明证书证明密钥对可用于跟踪用户或将同一用户的不同在线身份关联在一起。对此可以通过几种方式进行缓解,包括:

14.4.2. 存储在身份验证器中的个人身份信息隐私

认证器可以向客户端提供超出本规范定义的附加信息,例如, 使客户端能够提供丰富的用户界面,让用户选择用于认证过程凭证。如果认证器选择这样做,则不应在未成功执行用户验证的情况下暴露个人身份信息。如果认证器支持多个用户同时注册的用户验证,则认证器不应暴露除当前已验证用户之外的其他用户的个人身份信息。因此,无法进行用户验证认证器不应存储个人身份信息。

就本讨论而言,作为id成员传递的用户句柄,属于PublicKeyCredentialUserEntity,不被视为个人身份信息;有关详细信息,请参阅§ 14.6.1 用户句柄内容

这些建议旨在防止具有物理访问权限的攻击者从 身份验证器 中提取有关 身份验证器 已注册用户的个人身份信息。

14.5. 客户端的隐私考虑 客户端

14.5.1. 注册仪式隐私

为了保护用户免于在没有 同意 的情况下被识别,[[Create]](origin, options, sameOriginWithAncestors) 方法的实现需要小心,避免泄露可能使恶意的 WebAuthn 依赖方 区分这些情况的信息,其中 “排除” 意味着 凭证 列表中至少有一个由 依赖方excludeCredentials 标记为 绑定身份验证器

如果上述情况是可区分的,那么信息泄露可能会让恶意的 依赖方 通过探测哪些 凭证 可用,从而识别用户。例如,其中一种信息泄露的情况是,如果客户端在排除的 认证器 可用时立即返回失败响应。在这种情况下,尤其是当排除的 认证器 是一个 平台认证器 时,依赖方 可以检测到 仪式 在超时前被取消,而且是在用户可能手动取消之前,因此可以推断出在 excludeCredentials 参数中列出的一些 凭证 对用户是可用的。

然而,如果用户在返回可区分的错误之前已同意创建新凭证,则上述问题不再是一个问题,因为在这种情况下,用户已经确认了共享将泄露的信息的意图。

14.5.2. 认证仪式的隐私

为了保护用户不在没有同意的情况下被识别,[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)方法的实现需要注意不要泄露可能使恶意WebAuthn依赖方区分以下情况的信息,其中“named”表示依赖方allowCredentials中列出的凭证

如果上述情况是可区分的,则恶意的依赖方可以通过探测哪些凭证可用来识别用户,从而泄露信息。例如,一种此类信息泄露是当用户拒绝继续进行认证仪式同意时,客户端立即返回失败响应。在这种情况下,依赖方可以检测到是用户取消了仪式而不是超时,从而得出结论,即用户至少有一个列在allowCredentials参数中的凭证可用。

14.5.3. 操作系统账户之间的隐私

如果平台认证器包含在带有多用户操作系统的客户端设备中,则平台认证器客户端设备应协同工作,确保任何平台凭证的存在仅向创建该平台凭证的操作系统用户揭示。

14.6. 隐私考虑:依赖方

14.6.1. 用户句柄内容

由于用户句柄§ 14.4.2 存储在认证器中的个人识别信息的隐私中未被视为个人识别信息,依赖方不得在用户句柄中包含个人识别信息,如电子邮件地址或用户名。这包括个人识别信息的哈希值,除非哈希函数使用加盐并且盐值依赖方是私有的,因为哈希并不能防止可猜测输入值的探测。建议让用户句柄为64个随机字节,并将此值存储在用户的账户中。

14.6.2. 用户名枚举

在启动 注册身份验证仪式 时,存在 WebAuthn 依赖方 泄露其已注册用户的敏感信息的风险。例如,如果 依赖方 使用电子邮件地址作为用户名,且攻击者尝试对 "alex.mueller@example.com" 发起一个 身份验证 仪式,如果 依赖方 响应失败,但随后成功发起对 "j.doe@example.com" 的 身份验证仪式,那么攻击者可以推断出 "j.doe@example.com" 已注册,而 "alex.mueller@example.com" 未注册。依赖方 因此泄露了可能敏感的信息,即 "j.doe@example.com" 在该 依赖方 处有一个账户。

以下是一个非规范性、非详尽的措施列表,依赖方 可实现这些措施来减轻或防止因此类攻击导致的信息泄露:

14.6.3. 凭证ID的隐私泄露

本节不具规范性。

此隐私考虑适用于在非allowCredentials参数作为第一个认证步骤的认证过程中支持的依赖方。 例如,使用带有服务器端凭证的认证作为第一个认证步骤。

在这种情况下,allowCredentials 参数有泄露个人身份信息的风险,因为它将用户的 凭证 ID 暴露给未经身份验证的调用者。凭证 ID 设计上不应在不同的 依赖方 之间关联,但 凭证 ID 的长度可能暗示了创建它的 认证器 类型。 用户可能会在多个 依赖方 中使用相同的用户名和一组 认证器,因此 凭证 IDallowCredentials 中的数量及其长度可能作为一个全局关联句柄来去匿名化用户。 了解用户的 凭证 ID 也可能使得在仅能短暂物理访问用户的某个 认证器 时确认对用户身份的猜测。

为了防止此类信息泄露,依赖方 可以采取以下措施:

如果上述防范措施不可用, 即如果仅凭用户名需要暴露 allowCredentials 参数, 依赖方 可以通过返回虚拟的 凭证ID 来减轻隐私泄漏, 就像在 § 14.6.2 用户名枚举 中讨论的那样。

15. 可访问性注意事项

用户验证功能的认证器,无论是漫游认证器还是平台认证器,都应为用户提供多种用户验证方法。例如,既可以使用指纹传感器,也可以输入PIN码。当选择的方法因某种原因无法使用时,这样可以切换到其他用户验证方式。请注意,在漫游认证器的情况下,认证器和平台可能会协作提供用户验证方法,如PIN码输入[FIDO-CTAP]

依赖方注册时,应提供便利措施,以便用户在将来能够正确完成授权手势。这可能涉及为认证器命名、选择与设备相关联的图片,或输入自由格式的文本说明(例如,作为自我提醒)。

依赖于时间的仪式,例如注册仪式(见超时)或认证仪式(见超时),应遵循[WCAG21]准则2.2 足够时间。如果客户端平台确定某个依赖方提供的超时未适当地遵循上述[WCAG21]准则,则客户端平台可以相应调整超时。

16. 致谢

我们感谢以下人士对本规范的审查和贡献: Yuriy Ackermann、 James Barclay、 Richard Barnes、 Dominic Battré、 Julien Cayzac、 Domenic Denicola、 Rahul Ghosh、 Brad Hill、 Jing Jin、 Wally Jones、 Ian Kilpatrick、 Axel Nennker、 Yoshikazu Nojima、 Kimberly Paulhamus、 Adam Powers、 Yaron Sheffer、 Ki-Eun Shin、 Anne van Kesteren、 Johan Verrept, 以及 Boris Zbarsky。

感谢 Adam Powers 创建了整体的注册认证流程图(图1图2)。

我们感谢 Anthony Nadalin、John Fontana 和 Richard Barnes 作为 Web 认证工作组共同主席的贡献。

我们还感谢 Wendy Seltzer、Samuel Weiler 和 Harry Halpin 作为 W3C 团队联系人所做的贡献。

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[BCP47]
A. Phillips; M. Davis. 用于识别语言的标签。 2009年9月。IETF最佳现行实践。URL: https://tools.ietf.org/html/bcp47
[CREDENTIAL-MANAGEMENT-1]
Mike West. 凭据管理第1级。2019年1月17日。 WD。URL: https://www.w3.org/TR/credential-management-1/
[DOM4]
Anne van Kesteren. DOM标准。现行标准。URL: https://dom.spec.whatwg.org/
[ECMAScript]
ECMAScript语言规范。URL: https://tc39.es/ecma262/
[ENCODING]
Anne van Kesteren. 编码标准。现行标准。URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch标准。现行标准。URL: https://fetch.spec.whatwg.org/
[FIDO-APPID]
D. Balfanz; et al. FIDO AppID和Facet规范。2018年2月27日。FIDO联盟实施草案。URL: https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-appid-and-facets-v2.0-id-20180227.html
[FIDO-CTAP]
M. Antoine; et al. 客户端到认证器协议。 2018年2月27日。FIDO联盟实施草案。URL: https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html
[FIDO-Privacy-Principles]
FIDO联盟。FIDO 隐私原则。FIDO联盟白皮书。URL: https://fidoalliance.org/wp-content/uploads/2014/12/FIDO_Alliance_Whitepaper_Privacy_Principles.pdf
[FIDO-Registry]
R. Lindemann; D. Baghdasaryan; B. Hill. FIDO 预定义值的注册表。2018年2月27日。FIDO联盟实施草案。URL: https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-registry-v2.0-id-20180227.html
[FIDO-U2F-Message-Formats]
D. Balfanz; J. Ehrensvard; J. Lang. FIDO U2F原始消息格式。FIDO联盟实施草案。URL: https://fidoalliance.org/specs/fido-u2f-v1.1-id-20160915/fido-u2f-raw-message-formats-v1.1-id-20160915.html
[FileAPI]
Marijn Kruisselbrink; Arun Ranganathan. 文件API。 2019年9月11日。WD。URL: https://www.w3.org/TR/FileAPI/
[HTML]
Anne van Kesteren; et al. HTML标准。现行标准。URL: https://html.spec.whatwg.org/multipage/
[IANA-COSE-ALGS-REG]
IANA CBOR对象签名和加密(COSE)算法注册表。URL: https://www.iana.org/assignments/cose/cose.xhtml#algorithms
[IANA-WebAuthn-Registries]
IANA。Web认证(WebAuthn)注册表。 URL: https://www.iana.org/assignments/webauthn/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra标准。现行标准。URL: https://infra.spec.whatwg.org/
[PAGE-VISIBILITY]
Jatinder Mann; Arvind Jain. 页面可见性(第二版)。 2013年10月29日。REC。URL: https://www.w3.org/TR/page-visibility/
[Permissions-Policy]
Ian Clelland. 权限政策。2020年7月16日。 WD。URL: https://www.w3.org/TR/permissions-policy-1/
[RFC2119]
S. Bradner. 在RFC中用于指示需求等级的关键字。 1997年3月。最佳现行实践。URL: https://tools.ietf.org/html/rfc2119
[RFC3986]
T. Berners-Lee; R. Fielding; L. Masinter. 统一资源标识符(URI):通用语法。2005年1月。互联网标准。URL: https://tools.ietf.org/html/rfc3986
[RFC4648]
S. Josefsson. Base16,Base32和Base64数据编码。 2006年10月。建议标准。URL: https://tools.ietf.org/html/rfc4648
[RFC4949]
R. Shirey. 互联网安全术语表,第2版。 2007年8月。信息性。URL: https://tools.ietf.org/html/rfc4949
[RFC5234]
D. Crocker, Ed.; P. Overell. 增强型BNF用于语法规范:ABNF。 2008年1月。互联网标准。URL: https://tools.ietf.org/html/rfc5234
[RFC5280]
D. Cooper; et al. 互联网X.509公钥基础设施证书和证书撤销列表(CRL)规范。 2008年5月。建议标准。URL: https://tools.ietf.org/html/rfc5280
[RFC5890]
J. Klensin. 应用程序的国际化域名(IDNA):定义和文档框架。 2010年8月。建议标准。URL: https://tools.ietf.org/html/rfc5890
[RFC6454]
A. Barth. Web起源概念。 2011年12月。建议标准。URL: https://tools.ietf.org/html/rfc6454
[RFC7515]
M. Jones; J. Bradley; N. Sakimura. JSON Web签名(JWS)。 2015年5月。建议标准。URL: https://tools.ietf.org/html/rfc7515
[RFC8152]
J. Schaad. CBOR对象签名和加密(COSE)。 2017年7月。建议标准。URL: https://tools.ietf.org/html/rfc8152
[RFC8230]
M. Jones. 使用RSA算法与CBOR对象签名和加密(COSE)消息。 2017年9月。建议标准。URL: https://tools.ietf.org/html/rfc8230
[RFC8264]
P. Saint-Andre; M. Blanchet. PRECIS框架:在应用协议中准备,实施和比较国际化字符串。 2017年10月。建议标准。URL: https://tools.ietf.org/html/rfc8264
[RFC8265]
P. Saint-Andre; A. Melnikov. 准备,实施和比较表示用户名和密码的国际化字符串。 2017年10月。建议标准。URL: https://tools.ietf.org/html/rfc8265
[RFC8266]
P. Saint-Andre. 准备,实施和比较表示昵称的国际化字符串。 2017年10月。建议标准。URL: https://tools.ietf.org/html/rfc8266
[RFC8610]
H. Birkholz; C. Vigano; C. Bormann. 简明数据定义语言(CDDL):表示简明二进制对象表示法(CBOR)和JSON数据结构的符号约定。 2019年6月。IETF建议标准。URL: https://tools.ietf.org/html/rfc8610
[RFC8809]
Jeff Hodges; Giridhar Mandyam; Michael B. Jones. Web认证(WebAuthn)的注册表。 2020年8月。IETF建议标准。URL: https://www.rfc-editor.org/rfc/rfc8809
[RFC8949]
C. Bormann; P. Hoffman. 简明二进制对象表示法(CBOR)。 2020年12月。互联网标准。URL: https://tools.ietf.org/html/rfc8949
[SEC1]
SEC1:椭圆曲线密码学,版本2.0。URL: http://www.secg.org/sec1-v2.pdf
[SECURE-CONTEXTS]
Mike West. 安全上下文。2016年9月15日。 CR。URL: https://www.w3.org/TR/secure-contexts/
[SP800-800-63r3]
Paul A. Grassi; Michael E. Garcia; James L. Fenton. NIST特别出版物800-63:数字身份指南。 2017年6月。URL: https://pages.nist.gov/800-63-3/sp800-63-3.html
[TCG-CMCProfile-AIKCertEnroll]
Scott Kelly; et al. TCG 基础设施工作组:AIK证书注册的CMC配置文件。2011年3月24日。 已发布。URL: https://trustedcomputinggroup.org/wp-content/uploads/IWG_CMC_Profile_Cert_Enrollment_v1_r7.pdf
[TokenBinding]
A. Popov; et al. Token绑定协议版本1.0。 2018年10月。IETF建议标准。URL: https://tools.ietf.org/html/rfc8471
[TPMv2-EK-Profile]
TPM 家族2.0的TCG EK凭据配置文件。URL: https://www.trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf
[TPMv2-Part1]
可信平台模块库,第1部分:架构。 URL: https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.38.pdf
[TPMv2-Part2]
可信平台模块库,第2部分:结构。URL: https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
[TPMv2-Part3]
可信平台模块库,第3部分:命令。URL: https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-3-Commands-01.38.pdf
[URL]
Anne van Kesteren. URL标准。现行标准。URL: https://url.spec.whatwg.org/
[UTR29]
UNICODE文本分割。URL: http://www.unicode.org/reports/tr29/
[WCAG21]
Andrew Kirkpatrick; et al. Web内容可访问性指南(WCAG)2.1。 2018年6月5日。REC。URL: https://www.w3.org/TR/WCAG21/
[WebDriver]
Simon Stewart; David Burns. WebDriver。 2018年6月5日。REC。URL: https://www.w3.org/TR/webdriver1/
[WebIDL]
Boris Zbarsky. Web IDL。2016年12月15日。 ED。URL: https://heycam.github.io/webidl/

参考文献

[Ceremony]
Carl Ellison. 仪式设计与分析。2007年。URL: https://eprint.iacr.org/2007/399.pdf
[CSS-OVERFLOW-3]
David Baron; Elika Etemad; Florian Rivoal. CSS 溢出模块 第3级。2020年6月3日。WD。URL: https://www.w3.org/TR/css-overflow-3/
[EduPersonObjectClassSpec]
EduPerson。正在进行中。URL: https://refeds.org/eduperson
[FIDO-Transports-Ext]
FIDO 联盟。FIDO U2F 认证器传输扩展。FIDO 联盟建议标准。URL: https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-authenticator-transports-extension-v1.2-ps-20170411.html
[FIDO-UAF-AUTHNR-CMDS]
R. Lindemann; J. Kemp. FIDO UAF 认证器命令。FIDO 联盟实施草案。URL: https://fidoalliance.org/specs/fido-uaf-v1.1-id-20170202/fido-uaf-authnr-cmds-v1.1-id-20170202.html
[FIDOAuthnrSecReqs]
D. Biggs; 等。FIDO 认证器安全要求。FIDO 联盟最终文件。URL: https://fidoalliance.org/specs/fido-security-requirements-v1.0-fd-20170524/
[FIDOMetadataService]
R. Lindemann; B. Hill; D. Baghdasaryan. FIDO 元数据服务。2018年2月27日。FIDO 联盟实施草案。URL: https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-metadata-service-v2.0-id-20180227.html
[FIDOSecRef]
R. Lindemann; 等。FIDO 安全参考。2018年2月27日。FIDO 联盟实施草案。URL: https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-security-ref-v2.0-id-20180227.html
[FIDOU2FJavaScriptAPI]
D. Balfanz; A. Birgisson; J. Lang. FIDO U2F JavaScript API。FIDO 联盟建议标准。URL: https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-javascript-api-v1.2-ps-20170411.html
[ISOBiometricVocabulary]
ISO/IEC JTC1/SC37. 信息技术 — 词汇 — 生物识别技术。2012年12月15日。国际标准:ISO/IEC 2382-37:2012(E) 第一版。URL: http://standards.iso.org/ittf/PubliclyAvailableStandards/c055194_ISOIEC_2382-37_2012.zip
[RFC3279]
L. Bassham; W. Polk; R. Housley. 互联网X.509公钥基础设施证书和证书撤销列表(CRL)配置文件的算法和标识符。2002年4月。建议标准。URL: https://tools.ietf.org/html/rfc3279
[RFC5958]
S. Turner. 非对称密钥包。2010年8月。建议标准。URL: https://tools.ietf.org/html/rfc5958
[RFC6265]
A. Barth. HTTP 状态管理机制。2011年4月。建议标准。URL: https://httpwg.org/specs/rfc6265.html
[RFC8017]
K. Moriarty, Ed.; 等。PKCS #1:RSA密码规范版本2.2。2016年11月。信息性。URL: https://tools.ietf.org/html/rfc8017
[UAFProtocol]
R. Lindemann; 等。FIDO UAF 协议规范 v1.0。FIDO 联盟建议标准。URL: https://fidoalliance.org/specs/fido-uaf-v1.0-ps-20141208/fido-uaf-protocol-v1.0-ps-20141208.html
[WebAuthn-1]
Dirk Balfanz; 等。Web 认证:访问公共密钥凭证的API,第1级。2019年3月4日。REC。URL: https://www.w3.org/TR/webauthn-1/
[WebAuthnAPIGuide]
Web 认证 API 指南。实验性。URL: https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API

IDL 索引

[SecureContext, Exposed=Window]
interface PublicKeyCredential : Credential {
    [SameObject] readonly attribute ArrayBuffer              rawId;
    [SameObject] readonly attribute AuthenticatorResponse    response;
    AuthenticationExtensionsClientOutputs getClientExtensionResults();
};

partial dictionary CredentialCreationOptions {
    PublicKeyCredentialCreationOptions      publicKey;
};

partial dictionary CredentialRequestOptions {
    PublicKeyCredentialRequestOptions      publicKey;
};

partial interface PublicKeyCredential {
    static Promise<boolean> isUserVerifyingPlatformAuthenticatorAvailable();
};

[SecureContext, Exposed=Window]
interface AuthenticatorResponse {
    [SameObject] readonly attribute ArrayBuffer      clientDataJSON;
};

[SecureContext, Exposed=Window]
interface AuthenticatorAttestationResponse : AuthenticatorResponse {
    [SameObject] readonly attribute ArrayBuffer      attestationObject;
    sequence<DOMString>                              getTransports();
    ArrayBuffer                                      getAuthenticatorData();
    ArrayBuffer?                                     getPublicKey();
    COSEAlgorithmIdentifier                          getPublicKeyAlgorithm();
};

[SecureContext, Exposed=Window]
interface AuthenticatorAssertionResponse : AuthenticatorResponse {
    [SameObject] readonly attribute ArrayBuffer      authenticatorData;
    [SameObject] readonly attribute ArrayBuffer      signature;
    [SameObject] readonly attribute ArrayBuffer?     userHandle;
};

dictionary PublicKeyCredentialParameters {
    required DOMString                    type;
    required COSEAlgorithmIdentifier      alg;
};

dictionary PublicKeyCredentialCreationOptions {
    required PublicKeyCredentialRpEntity         rp;
    required PublicKeyCredentialUserEntity       user;

    required BufferSource                             challenge;
    required sequence<PublicKeyCredentialParameters>  pubKeyCredParams;

    unsigned long                                timeout;
    sequence<PublicKeyCredentialDescriptor>      excludeCredentials = [];
    AuthenticatorSelectionCriteria               authenticatorSelection;
    DOMString                                    attestation = "none";
    AuthenticationExtensionsClientInputs         extensions;
};

dictionary PublicKeyCredentialEntity {
    required DOMString    name;
};

dictionary PublicKeyCredentialRpEntity : PublicKeyCredentialEntity {
    DOMString      id;
};

dictionary PublicKeyCredentialUserEntity : PublicKeyCredentialEntity {
    required BufferSource   id;
    required DOMString      displayName;
};

dictionary AuthenticatorSelectionCriteria {
    DOMString                    authenticatorAttachment;
    DOMString                    residentKey;
    boolean                      requireResidentKey = false;
    DOMString                    userVerification = "preferred";
};

enum AuthenticatorAttachment {
    "platform",
    "cross-platform"
};

enum ResidentKeyRequirement {
    "discouraged",
    "preferred",
    "required"
};

enum AttestationConveyancePreference {
    "none",
    "indirect",
    "direct",
    "enterprise"
};

dictionary PublicKeyCredentialRequestOptions {
    required BufferSource                challenge;
    unsigned long                        timeout;
    USVString                            rpId;
    sequence<PublicKeyCredentialDescriptor> allowCredentials = [];
    DOMString                            userVerification = "preferred";
    AuthenticationExtensionsClientInputs extensions;
};

dictionary AuthenticationExtensionsClientInputs {
};

dictionary AuthenticationExtensionsClientOutputs {
};

dictionary CollectedClientData {
    required DOMString           type;
    required DOMString           challenge;
    required DOMString           origin;
    boolean                      crossOrigin;
    TokenBinding                 tokenBinding;
};

dictionary TokenBinding {
    required DOMString status;
    DOMString id;
};

enum TokenBindingStatus { "present", "supported" };

enum PublicKeyCredentialType {
    "public-key"
};

dictionary PublicKeyCredentialDescriptor {
    required DOMString                    type;
    required BufferSource                 id;
    sequence<DOMString>                   transports;
};

enum AuthenticatorTransport {
    "usb",
    "nfc",
    "ble",
    "internal"
};

typedef long COSEAlgorithmIdentifier;

enum UserVerificationRequirement {
    "required",
    "preferred",
    "discouraged"
};

partial dictionary AuthenticationExtensionsClientInputs {
  USVString appid;
};

partial dictionary AuthenticationExtensionsClientOutputs {
  boolean appid;
};

partial dictionary AuthenticationExtensionsClientInputs {
  USVString appidExclude;
};

partial dictionary AuthenticationExtensionsClientOutputs {
  boolean appidExclude;
};

partial dictionary AuthenticationExtensionsClientInputs {
  boolean uvm;
};

typedef sequence<unsigned long> UvmEntry;
typedef sequence<UvmEntry> UvmEntries;

partial dictionary AuthenticationExtensionsClientOutputs {
  UvmEntries uvm;
};

partial dictionary AuthenticationExtensionsClientInputs {
    boolean credProps;
};

dictionary CredentialPropertiesOutput {
    boolean rk;
};

partial dictionary AuthenticationExtensionsClientOutputs {
    CredentialPropertiesOutput credProps;
};

partial dictionary AuthenticationExtensionsClientInputs {
    AuthenticationExtensionsLargeBlobInputs largeBlob;
};

enum LargeBlobSupport {
  "required",
  "preferred",
};

dictionary AuthenticationExtensionsLargeBlobInputs {
    DOMString support;
    boolean read;
    BufferSource write;
};

partial dictionary AuthenticationExtensionsClientOutputs {
    AuthenticationExtensionsLargeBlobOutputs largeBlob;
};

dictionary AuthenticationExtensionsLargeBlobOutputs {
    boolean supported;
    ArrayBuffer blob;
    boolean written;
};

问题索引

WHATWG HTML 工作组正在讨论是否在浏览上下文获得或失去焦点时提供一个钩子。如果提供钩子,上述段落将更新以包括该钩子。 有关更多详细信息,请参阅 WHATWG HTML 工作组问题 #2711