人们经常看到密码是网络身份验证的原罪。密码很容易被猜中,很容易被攻破。在网络上频繁重复使用相同的密码会让入侵变得更加有利可图。随着密码变得更强、更独特,它们可能很快就会对许多用户变得不可用。密码看起来确实臭名昭著,但密码本身是问题所在,还是将其用作身份验证的唯一因素?
许多人相信后者,因此多因素身份验证变得越来越流行。引入第二个因素确实解决了密码的大部分安全问题,但它不可避免地会通过额外的步骤使整个身份验证体验变得繁琐。因此,多因素认证并没有成为网络上事实上的认证机制。Face ID和Touch ID for Web提供了多因素身份验证的安全保证和易用性。它在单个步骤中提供多因素身份验证。使用这项在超过10亿台苹果设备上可用的技术,网络开发人员现在可以广泛地提供传统的多因素身份验证,并提供流畅、方便的体验。而建立在网络身份验证API之上的Face ID和Touch ID也可以抵抗网络钓鱼。
这篇博客文章扩展了WWDC 2020“Meet Face ID and Touch ID for the Web”会议的内容,提供了详细的示例来帮助开发人员采用这项新技术,包括如何管理不同的用户代理用户界面、如何将用户手势从用户激活的事件传播到WebAuthn API调用,以及如何解释Apple匿名证明。本文最后将总结苹果平台认证器的独特特点和安全密钥支持现状。如果您以前没有听说过WebAuthn,强烈建议您首先观看WWDC 2020会议,该会议涵盖了基本概念。不然的话,请慢用。
虽然在WebAuthn流期间不需要用户代理向用户提供UI指导,但实际上所有用户代理都需要这样做。这允许用户代理分担来自网站的一些管理用户体验的负担,但它给网站带来了另一个复杂性,因为每个用户代理在其UI中呈现WebAuthn仪式的方式不同。WebAuthn仪式可以是认证过程,也可以是注册过程。本节介绍WebAuthn仪式选项如何映射到WebKit/Safari的UI,以及推荐的用于Web的Face ID和Touch ID的用户体验。
一个挑战是管理平台验证器和安全密钥之间的不同用户体验。虽然WebAuthn API允许同时向用户呈现这两个选项,但这不是最好的方法。首先,大多数用户可能只熟悉平台认证器的品牌,即苹果平台上的Face ID和Touch ID,但对安全密钥并不熟悉。同时提供这两种服务可能会让用户感到困惑,并使他们很难决定要做什么。其次,平台认证器与安全密钥具有不同的行为和用例。例如,Face ID和Touch ID适合在大多数安全密钥不是的情况下作为一种更方便的替代登录机制使用。并且存储在安全密钥中的凭证通常可以跨不同的设备和平台使用,而存储在平台认证器中的凭证通常绑定到平台和设备。因此,最好将这两个选项分别呈现给用户。
以下是为Web调用Face ID和Touch ID的推荐方式。下面是用于注册仪式的对应Safari用户界面。在这里,选择要在对话框中显示的依赖方ID。
常量选项={public Key:{Rp:{name:";example.com";},用户:{name:";[email protected]";,id:userIdBuffer,displayName:";John Appleseed";},pubKeyCredParams:[{type:";public-key";,alg:-7}],challengeBuffer,AuthenticatorSelection:{AuthenticatorAttach:";Platform";};const public KeyCredential=等待导航器。全权证书。创建(选项);
基本选项是指定AuthenticatorSelection:{AuthenticatorAttach:";Platform";},它告诉WebKit只调用平台验证器。在返回public KeyCredential之后,最佳实践之一是将凭据ID存储在服务器集的安全httpOnly cookie中,并将其传输标记为";内部";。然后,此cookie可用于改善未来身份验证仪式的用户体验。
为了保护用户免受跟踪,WebAuthn API不允许网站查询设备上是否存在凭据。然而,这一重要的隐私功能需要网站在单独的源中存储提供的凭证ID,并在身份验证仪式之前对其进行查询,这需要付出一些额外的努力。单独的源通常在后端服务器上。考虑到安全密钥可以跨平台使用,这种做法对安全密钥非常有效。遗憾的是,它不适用于平台验证器,因为凭据只能在创建凭据的设备上使用。服务器端源无法判断特定平台验证器是否确实保留了凭证。因此,cookie特别有用。此Cookie不应通过Document.cookie API设置,因为Safari的智能跟踪防御将此类Cookie的有效期限制为七天。将这些凭据标记为内部凭据也很重要,这样网站就可以在身份验证仪式选项中提供凭据,以防止WebKit同时要求用户提供安全密钥。
下面是用于身份验证仪式的两个不同UI。第一个示例针对用户代理只有一个凭据的情况进行了简化,而第二个示例显示了用户代理如何允许用户从多个凭据中选择一个。对于这两种情况,只选择显示在注册仪式中提交的user.name。对于第二种情况,列表的顺序根据凭证的上次使用日期进行排序。WebKit跟踪上次使用的日期。因此,网站不需要担心这一点。
常量选项={public Key:{challengl:challengeBuffer,allowCredentials:[{type:";public-key";,id:redentialIdBuffer1,transports:[";Internal";]},//...。可以提供更多凭据ID。]}};const public KeyCredential=等待导航器。全权证书。GET(选项);
需要注意的是,尽管可以对WebKit进行改进,以便只要在平台验证器中找到所有允许的凭证,就不需要传输:[";Internal&34;]来防止WebKit要求用户提供安全密钥,但这只适用于愉快的路径。在没有找到凭据的情况下,这个额外的属性可以告诉WebKit显示错误消息,而不是要求用户提供安全密钥。
尽管不鼓励使用以下用法,WebKit/Safari已经准备了专用UI,以允许用户选择除平台验证器之外的安全密钥。下面是注册仪式用的。
从上面的注册仪式代码片段中删除AuthenticatorSelection:{AuthenticatorAttach:";Platform";}即可获得上述对话框。
如果上面身份验证仪式代码片段中的allowCredentials数组中的任何条目没有transports:[";Internal";]属性,则会显示上面的对话框。
需要注意的是,在显示UI之后,这两种情况下都可以立即使用安全密钥。“Use Security Key”和“Account From Security Key”选项用于显示如何与安全密钥交互的说明。
对于身份验证仪式,allowCredentials是可选的。但是,省略它将导致WebKit/Safari的UI中出现不确定的行为。如果找到凭据,将显示上面的身份验证仪式UI。如果找不到凭据,WebKit将要求用户提供其安全密钥。因此,强烈建议不要省略此选项。
未经请求的权限提示令人讨厌。Mozilla已经进行了调查[1,2]来验证这一点。尽管WebAuthn提示不像今天的通知提示那样经常出现在网络上,但随着Face ID和Touch ID for Web的发布,这种情况将会改变。
网站不会为了好玩而要求通知许可。他们这样问是因为通知可以将用户带回他们的网站,并增加他们的日活跃用户指标。在WebAuthn提示中可以找到类似的经济激励,特别是当平台认证器可用时,因为履行的认证请求导致用户的高保真、持久的唯一标识符。这是关于身份验证的普遍真理,这就是为什么许多站点甚至在用户与站点交互之前就要求提供它。虽然WebAuthn凭据将不可避免地被利用来向用户提供定向广告,但至少可以利用Mozilla在Firefox中为通知权限提示所做的类似保护,以减少这些WebAuthn提示对用户的烦扰,即要求WebAuthn API的用户手势来消除恼人的“加载”提示。
我们在一段时间前就预见到了这个问题,并在WebAuthn规范上提交了一个问题,但当时并没有得到太多关注。原因之一是这是一个突破性的变化。另一个原因是,安全密钥的风险不是很高,因为它们不是那么受欢迎,并且并不总是附着在平台上。不请自来的提示量令人惊讶地低。这种情况随着Face ID和Touch ID for Web的发布而有所不同。因此,网页的Face ID和Touch ID需要用户手势才能运行。(为了向后兼容,安全密钥不需要用户手势。)。
用户手势是通知WebKit当前JavaScript上下文的执行是用户交互的直接结果的指示器,或者更准确地说,来自用户激活事件的处理程序,例如TouchEnd、Click、DoubleClick或Keydown事件[3]。WebAuthn API需要用户手势意味着API调用必须在上面的JavaScript上下文中进行。通常,用户手势不会传播到上下文中的任何异步执行器。由于网站通常在调用WebAuthn API之前从服务器异步获取质询,因此WebKit允许WebAuthn API接受通过XHR事件和Fetch API传播的用户手势。以下是网站如何从用户激活的事件调用Web的Face ID和Touch ID的示例。
//在onClick事件之前获取challengeBuffer。纽扣。AddEventListener(";单击";,async()=>;{常量选项={public Key:{...。Challenges:challengeBuffer,...}};const public KeyCredential=等待导航器。全权证书。创建(选项);});
纽扣。AddEventListener(";click";,()=>;{const xhr=new XMLHttpRequest();xhr。Onreadystatechange=异步函数(){if(this.。ReadyState==4&;&;this。状态==200){常量质询=此。响应文本;常量选项={public Key:{...。质询:heStringToUint8Array(质询),//a自定义帮助器...}};const public KeyCredential=等待导航器。全权证书。创建(选项);}};xhr。Open(";post";,";/webkit/webauthn/challengl";,true);xhr。SetRequestHeader(";Content-type";,";application/x-www-form-urlencode";);xhr。Send();});
纽扣。AddEventListener(";click";,async()=>;{const response=等待获取(";/webkit/webauthn/challengl";,{method:";post";});const challenges=等待响应。Text();常量选项={public Key:{...。质询:heStringToUint8Array(质询),//a自定义帮助器...}};const public KeyCredential=等待导航器。全权证书。创建(选项);});
需要注意的是,可读流还不能传播用户手势(相关错误)。此外,对于XHR事件和FETCH API,用户手势都将在10秒后过期。
纽扣。AddEventListener(";单击";,()=>;{setTimeout(async()=>;{const options={...};const public KeyCredential=等待导航器。全权证书。创建(选项);},500);});
在iOS 14、iPadOS 14和MacOS Big Sur Beta Seed 1上,只支持第一种情况。多亏了开发人员的早期反馈,我们能够识别限制并添加后来的案例。这也帮助我们认识到,用户手势在Web开发人员中并不是一个很好理解的概念。因此,我们将为HTML规范做出贡献,并帮助建立一个良好的用户手势概念,以保持浏览器供应商之间的一致性。根据进展情况,我们可能会重新考虑将用户手势要求扩展到安全密钥。
认证是一项可选功能,它为网站提供验证者出处的加密证明,以便受特殊规定限制的网站可以做出信任决定。面向网络的Face ID和Touch ID提供Apple匿名认证。一旦经过验证,此证明可保证执行WebAuthn注册仪式的是真实的Apple设备,但不能保证该设备上运行的操作系统未被篡改。如果操作系统未被篡改,它还保证刚刚生成的凭证的私钥受到安全飞地的保护,并且私钥的使用受到Face ID或Touch ID的保护。(注意:如果生物识别连续多次失败,则防护退回到设备密码。)。
Apple匿名认证是此类认证中的第一个,提供类似于匿名CA的服务,其中认证者与其制造商拥有的云操作的CA合作,动态生成每个凭证的认证证书,以便认证声明中不会向网站泄露认证者的身份信息。此外,在与注册仪式相关的数据中,只有凭证的公钥连同串联的认证器数据和客户端数据的散列被发送到CA进行认证,并且CA不会存储这些数据中的任何一个。这种方式使得整个认证过程的私密性得以保护。此外,此方法避免了基本证明的安全缺陷,即单个设备的危害会导致使用相同证明证书的所有设备的证书被吊销。
常量选项={public Key:{...。证明:";direct";,//基本选项...}};const public KeyCredential=等待导航器。全权证书。创建(选项);
这是Apple匿名证明声明格式的定义。问题1453正在跟踪将此语句格式添加到WebAuthn标准的进度。
$$attStmtType//=(fmt:";apple";,attStmt:appleStmtFormat)appleStmtFormat={x5c:[redCert:Bytes,*(caCert:Bytes)]}
上述字段的语义如下:X5C CredCert后跟其证书链,每个证书链都以X.509格式编码。CredCert用于证明的凭据公钥证书,以X.509格式编码。
验证attStmt是符合上面定义的语法的有效CBOR,并对其执行CBOR解码以提取包含的字段。
验证NONCE是否与CredCert中具有OID(1.2.840.113635.100.8.2)的扩展名的值匹配。这里的随机数用于证明证明是有效的,并保护AuthenticatorData和客户端数据的完整性。
如果成功,则返回表示证明类型匿名CA和证明信任路径x5c的实现特定值。
最后一步是验证x5c是从redCert到Apple WebAuthn根证书的有效证书链,然后证明证明。(此步骤通常由利用x5c[4]的不同类型的证明共享。)。需要注意的是,即使启用了证明,AAGUID也是全零的,因为所有支持Web的Face ID和Touch ID的Apple设备都应具有本节开头说明的相同属性,并且任何其他设备都不能请求Apple匿名证明。
以下是关于苹果平台认证器的独特特性的总结,即用于网络的Face ID和Touch ID。
在iOS 14、iPadOS 14和MacOS Big Sur上的Safari、SFSafariViewController和ASWebAuthenticationSession中提供了用于Web的Face ID和Touch ID。对于MacOS,带有下层操作系统的Safari 14将不会获得此功能,因为证明依赖于新的系统框架。
无论指定哪个选项,平台验证器生成的所有公钥凭据都是驻留密钥。
只能通过Safari&>历史&>清除历史…清除所有凭据。在Mac Safari或设置>;Safari>;清除iOS&;iPadOS的历史记录和网站数据。
签名计数器未实现,因此始终为零。Secure Enclave用于防止凭证私钥泄露,而不是软件保护。
除了为网络引入Face ID和Touch ID之外,所有支持的MacOS上的iOS 14、iPadOS 14和Safari 14还改进了对安全密钥的支持,包括PIN输入和账户选择。以下是当前支持的功能列表。从iOS13.3、iPadOS13.3和Safari13开始,除了前面提到的两个之外,所有这些都得到了支持。
WebAuthn级别1中的所有必须功能以及除CollectedClientData.tokenBinding和大多数扩展之外的所有可选功能。目前仅支持APPID扩展名。
与Web的Face ID和Touch ID一样,Safari、SFSafariViewController和ASWebAuthenticationSession也提供安全密钥支持。
在这篇博客文章中,我们介绍了用于网络的Face ID和Touch ID。我们相信这是网络身份验证的一次巨大飞跃。它是一种很好的登录方式,特别是对于传统的多因素身份验证机制。在这项技术的帮助下,我们相信多因素身份验证将取代单一因素密码成为事实上的Web身份验证机制。开发者们,请今天就开始测试这一功能,并通过在Twitter(@webkit,@alanwaketan,@jonathandavis)上发送反馈或提交错误来让我们知道它是如何为您工作的。