现实生活中的WebAuthn

在2019年9月,Mail.ru Mail团队支持WebAuthn技术。我们成为世界上第一个实现了使用电子密钥而不是密码登录到您帐户的功能的电子邮件服务。现在,我们所有的用户都可以使用此机会,您可以在设置中将电子钥匙绑定到您的帐户,然后自由使用它进行输入。



我们已经在哈布雷(Habré)上写过有关此事件的新闻。在本文中,我想更多地讨论在我们的服务中实现WebAuthn的原因以及使用此技术的技术方面。

什么是WebAuthn,为什么需要


在现代世界中,大多数Internet服务都使用密码来验证用户身份。密码的优点是操作简便:访问必需的资源,您只需要知道密码并正确输入即可。

但是,密码的弊端往往胜过它们的优点:

  • 如果密码很简单-您可以找回密码;
  • 如果在多个服务中使用了相同的密码,则破坏其中之一,攻击者就可以访问所有其他服务;
  • 密码容易受到网络钓鱼攻击;
  • 强大而独特的密码很难记住,因此用户被迫在贴纸上写下密码并将其粘贴在显示器上,从那里很容易被窃取,盗取或丢失。

为了摆脱密码的缺点并使身份验证过程更加安全,出现了多种替换密码的方法-这是使用通过SMS或PUSH通知发送给用户的一次性代码,或者使用特殊的TOTP代码生成器应用程序,用户可以通过该应用程序登录帐户而无需输入密码。

公司如微软雅虎亚马逊考虑使用密码认证方式彻底摒弃在他们的服务使用密码。 Mail.ru邮件也不例外,我们长期以来一直支持使用一次性代码登录,这使用户不必记住复杂而安全的密码,就可以快速访问其帐户。

密码的另一种替代方法是使用电子密钥(安全密钥,另一个名称-电子认证器)进行认证。其操作原理基于非对称加密技术的使用,并在FIDO(快速在线身份证明)联盟开发的FIDO2协议系列中进行了描述。

W3C在2019年3月发布了该标准第一个版本。,它描述了基于浏览器的JS API,可让您与电子钥匙进行交互。该标准收到了建议状态和名称Web身份验证:用于使用公共密钥:一级访问凭据的API(Web身份验证:用于访问公共密钥凭据级别1的API)-简称WebAuthn。

WebAuthn的工作方式


在使用WebAuthn的身份验证过程中,确定了以下主要角色:

  • 客户端(WebAuthn客户端)-支持WebAuthn API的浏览器;
  • Web应用程序-使用WebAuthn API与凭据交互在客户端上运行的应用程序;
  • 凭据(公共密钥凭据)-与用户帐户关联的一对公共和私有加密密钥;
  • 身份验证器(一种设备或程序)创建用户凭据,并使用这些凭据对依赖方的请求进行签名(另一个名称是电子密钥);
  • 依赖方(WebAuthn依赖方)-Web服务器-存储与用户帐户关联的公钥,并使用存储在身份验证器中的私钥来验证其请求签名的有效性。

WebAuthn API仅允许您执行两项操作。它允许您创建新的凭据,并使用已创建的凭据对来自服务器的请求进行签名。

凭证的创建(MakeCredential



创建凭证的阶段方案,取自w3.org

在此阶段,电子钥匙已注册到用户帐户中。在身份验证器内部,将生成一对新的公用密钥和专用密钥,并将公用密钥发送并存储在服务器上的用户帐户中。

const credential = await navigator.credentials.create({
    publicKey: publicKeyMakeCredentialOptions
});

使用已创建的凭据对请求进行签名(GetAssertion



来自w3.org的带有证书验证的阶段计划

在该步骤,检查用户是否具有认证者,该认证者的公钥存储在用户帐户中。随机令牌在身份验证器内用私钥签名,然后发送到服务器,服务器在服务器上检查签名是否正确。因此,如果签名是正确的,那么我们可以得出结论,用户确实拥有该验证者。

const assertion = await navigator.credentials.get({
    publicKey: publicKeyGetAssertionOptions
});

您可以在此视频中看到使用WebAuthn输入Mail.ru Mail的过程的演示

您可以在WebAuthn规范(例如,在这篇中型文章中)中了解有关WebAuthn API本身的更多信息

因此,WebAuthn的工作基于电子密钥的使用。它是什么?

电子钥匙


电子密钥(有时也称为“ WebAuthn密钥”,例如安全密钥)是实现FIDO2交互协议的设备或程序。

在WebAuthn规范和家庭级别中,所有电子钥匙都归为以下两类之一:

  • 与平台无关的密钥(漫游身份验证器);
  • 平台验证器

与平台无关的密钥是外部物理设备,例如Yubico的Yubikey或Google的Titan安全密钥。通常,此类身份验证器通过USB,NFC或BLE连接到用户的计算机或智能手机。与此类设备的通信使用特殊的CTAP协议(客户端到身份验证器协议)进行。

要开始使用物理电子钥匙,用户需要将其绑定到他的帐户一次。之后,用户有机会使用此电子密钥在任何其他设备和任何浏览器中输入。


各种独立于平台的密钥的示例,取自theverge.com

如果第一类按键的操作机制或多或少清晰,那么我想更详细地介绍第二类。

在第二种情况下,将生成并存储公用和专用加密密钥,而不是将其存储在外部物理设备内部,而是将某些软件模块存储在计算机或智能手机内部。可以在特定的应用程序级别或操作系统级别上实现此软件模块。例如,在计算机内部的安全芯片中,只有当您登录并证明自己确实是您的操作系统时,操作系统才能授予访问权限。

在不同浏览器中的大多数现代实现中,OS要求用户使用指纹或输入用户帐户的密码来确认自己。需要明确的一点是,尽管用户需要将手指放在指纹扫描仪上才能使用此类按键,但指纹本身并未存储在任何地方,也不会在任何地方传输。这只是操作系统或浏览器验证用户的方式。


使用特定于平台的身份验证器。

WebAuthn API仅将编码的公共密钥信息或签名的随机令牌返回到Web服务,然后将其存储在服务器端并进行检查。

因此,在内置身份验证器的情况下,将只能在将其附加到帐户的浏览器和设备上使用它。换句话说,与平台相关的密钥将必须在打算登录帐户的每个设备/浏览器上分别注册。

将来,预计将出现更多方式,这些方式将使用户能够激活特定于平台的身份验证器的使用,例如,通过使用面部扫描或通过从设备输入PIN码。

当创建凭证或计算签名,你可以指定认证的,它有两个值的特殊参数的首选类型- cross-platformplatform。在这种情况下,将要求用户仅使用一种类型的电子钥匙。

const credential = await navigator.credentials.create({
    publicKey: {
        authenticatorSelection: {
            authenticatorAttachment: 'cross-platform',
        },
        ...,
    },
});

WebAuthn的好处


WebAuthn技术对用户和开发人员有什么好处?

  • 用户无需记住和输入任何密码,服务器也无需分别存储用户密码,密码所具有的所有缺点均已消除。与拦截通过不安全连接以电子方式发送的密码相比,从用户那里窃取物理身份验证器要困难得多,并且网站上公开密钥的泄漏不会打开隐藏在设备中的私有密钥。
  • origin , . origin . , (thesslstore.com, yubico.com) .
  • WebAuthn - . - web- , .
  • WebAuthn本身作为API,可为开发人员提供对身份验证器实现的抽象,并允许您编写一次代码,然后将其与所有类型和类型的电子钥匙一起使用。因此,WebAuthn是用于用户身份验证的可扩展解决方案。

关于为何WebAuthn比密码更安全的信息- 针对开发人员的WebAuthn:改善身份验证的5个步骤有关安全密钥的入门

WebAuthn支持


软件狗身份验证是否在您的设备上有效取决于几个不同的因素。从您的浏览器是否支持WebAuthn API开始,以计算机上的连接器以及身份验证器支持的通信方式开始。 WebAuthn的性能还很大程度上取决于您使用的设备和操作系统。

根据caniuse.com,在撰写本文时,WebAuthn API受80.5%的用户支持。根据Mail.ru用户的统计数据,该数字顺序相同-79.8%。但是,为了在所有这些浏览器中使用WebAuthn,您肯定需要一个外部电子钥匙。

并非所有支持WebAuthn API的浏览器都可以使用与平台相关的键(为方便起见,稍后将这些键称为“指纹”)。另外,要使用这样的密钥,仅安装可以使用它们的浏览器是不够的。您的设备和操作系统还必须具有适当的模块/传感器,并能够与其交互。在所有Mail.ru用户中,只有9.0%的用户可以添加特定于平台的密钥。

我将简要介绍一下不同操作系统和浏览器对WebAuthn的支持。

视窗


Windows上的WebAuthn支持非常好。Windows Hello身份验证子系统可以使用电子密钥。因此,此操作系统的所有最新浏览器版本-Microsoft Edge,Google Chrome,Opera和Mozilla Firefox-支持使用外键和指纹。Internet Explorer API WebAuthn不支持。


的Linux


外部验证器通常受任何现代Linux发行版以及Google Chrome,Chromium和Mozilla Firefox等浏览器的支持。但是,在某些系统上,可能需要使用其他设置才能使用外键

安卓系统


Android上的WebAuthn支持也不错。Google Chrome,Opera和Mozilla Firefox-支持使用外键和指纹。但是Microsoft Edge for Android完全不支持WebAuthn API。Firefox中还有一个错误-使用该选项指定首选的身份验证器类型对此无效authenticatorAttachment


的iOS


在适用于iOS操作系统的所有浏览器中,WebAuthn仅支持移动Safari版本13.3。而且,他只能使用外部电子钥匙。其他适用于iOS的浏览器根本不支持WebAuthn。

苹果系统


Microsoft Edge,Google Chrome,Opera和Mozilla Firefox支持在macOS上使用外键。Google Chrome浏览器还支持指纹识别,使您可以将WebAuthn与Touch ID一起使用。


如果在Edge,Opera和Chrome中用于与WebAuthn进行交互的界面相同,则Firefox在此处已脱颖而出。使用WebAuthn时,不是在Firefox中弹出漂亮的窗口,而是在屏幕角落显示一个小的通知。如果您不小心单击了某个页面,它只会折叠起来,使用户无所适从。



但是,Safari尚不支持WebAuthn。 Safari 13宣布了对WebAuthn的支持,它将在macOS 10.15 Catalina上提供。但是,在撰写本文时,我的检查表明Safari中的WebAuthn API(尽管存在)非常不稳定,并且不能与所有身份验证器一起使用。像其移动版本一样,Safari不能与内置电子钥匙一起使用。此外,它还不支持任何外来电子钥匙。

因此,我们意识到,除了支持问题之外,WebAuthn在UI中的差异更大。这些差异导致这样的事实,您必须向用户更详细地解释使用电子钥匙来使用入口所需的条件。此外,随着每个新浏览器版本的出现,这些弹出窗口可能会发生变化,并且今天使用WebAuthn的过程可能与昨天有所不同。

很清楚为什么会这样。WebAuthn技术还很年轻,浏览器开发人员仍在尝试不同类型的实现。我们只能希望,随着时间的推移,浏览器中对WebAuthn的支持将稳定下来,我们将能够不受限制地使用它。

身份验证者注册


如果我们给用户机会在他的帐户中注册不同的电子钥匙,那么他应该有机会查看他们的清单并从中删除过时或不必要的清单。例如,在密钥之一被泄露的情况下,这可能是有用的。

WebAuthn API的设计使得在创建和使用凭据时,客户端无法获得有关使用的身份验证器的类型,类型和名称的任何信息。因此,我们没有任何可以区分一个键和另一个键的数据。列表中的所有键将被均等地显示,而不会区分功能。问题:该怎么办?


如果在创建凭据时请求所谓的凭据,则可以获得有关所使用的身份验证器的一些信息。认证。认证是认证者向服务器证明其真实性的一种方式。在某些情况下,可以从认证中获取有关密钥制造商的信息。但是在一般情况下,所使用的数据仍然不足以清楚地区分与帐户相关联的一个电子钥匙。

const credential = await navigator.credentials.create({
    publicKey: {
        attestation: 'direct',
         ...,
    },
});

因此,将密钥连接到Mail中的帐户后,我们为用户提供了为新创建的记录分配一些名称的机会。而且用户可以通过此名称将一个键与另一个键区分开。

客户端和服务器可用的信息不包含有关身份验证器类型的任何数据这一事实导致WebAuthn的另一个不愉快的功能。

假设有一个用户仅在其智能手机中的帐户中添加了一个指纹。当我们想使用WebAuthn API登录时,我们传入一个函数调用navigator.credentials.get与帐户关联的所有键的列表。但是浏览器无法从该列表中确定设备上存在哪些身份验证器,哪些不存在。因此,他被迫始终向用户提供使用WebAuthn的权限。

因此,即使试图登录不支持通过指纹进行身份验证的计算机上的帐户,仍会向用户提供使用WebAuthn的权限。

为了在这种情况下实现正确的行为,您需要改进WebAuthn标准本身。例如,对有关是否使用跨平台密钥或指纹来创建信息进行编码,而在事先已知无法使用WebAuthn用户的情况下,不向WebAuthn用户提供信息。

在某些情况下,有一些方法可以解决此问题。例如,允许用户仅单独注册指纹和物理密钥。并且在使用密钥时,请在显然不支持它们的设备上过滤指纹。但是这种方法不能完全解决问题。并且没有可靠的方法来解决此问题。

我们的用户尚未收到有关此行为的投诉,因此我们目前正在调查此功能并决定将来要做什么。

WebAuthn在不同的子域上工作


如前所述,WebAuthn提供了针对网络钓鱼的开箱即用保护。注册电子钥匙时,将存储origin该钥匙在其上注册的信息。 WebAuthn不允许在资源上使用此电子密钥,而另一个则不能使用origin

大型Web服务(例如Mail.ru)通常使用几个不同的域来工作。例如,我们有一个e.mail.ru用于Mail和cloud.mail.ruCloud 的域。并且在它们每个上,我们都有一种通用的授权形式。在这种情况下,标准的WebAuthn设置是不够的。为了使我们可以使用origin在另一个上注册的密钥origin,这两个域必须具有公共后缀(大于第一级的公共子域)。

例如在域e.mail.rucloud.mail.ru常见的后缀mail.ru

在这种情况下,注册和使用电子密钥时,我们可以在request选项中指定一个rpId相等的参数mail.ru,然后可以在https://mail.ru子域本身及其任何密钥上使用相同的密钥。

const credential = await navigator.credentials.create({
    publicKey: {
        rp: {
            name: 'Mail.ru Group',
            id: 'mail.ru',
        },
        ...,
    },
});

iframe中的WebAuthn工作


出于安全原因,禁止在跨域iframe中调用WebAuthn方法。我们的项目使用一个授权表单,位于https://account.mail.ru/login,并且当我们想在任何其他项目(例如,邮件或云中)中显示授权表单时,实际上会将iframe添加到页面中在其中打开该网址。通过该解决方案,我们可以同时在使用表单的所有项目上同时更新表单本身,并简化统计信息的收集,并改善用户的用户体验,使他能够继续使用原来的服务。



在我们的案例中,从iframe内部调用WebAuthn方法的限制使我们寻求解决方法,因为我们希望有机会在显示授权表单的任何地方通过WebAuthn登录。

我们做了什么。要在所有服务上打开授权表,我们使用一个小型库,该库实际上仅在页面上使用正确的url创建一个iframe,并在加载其内容后在页面上显示该iframe。该库支持通过postMessage与iframe进行通信并使用它,例如在调整其内容大小时调整iframe的大小。

我们提出并实现了以下机制:

  1. 在使用WebAuthn的授权应用程序中,我们确定是否现在在iframe中打开;
  2. 如果我们是在iframe中打开的,那么我们将调用参数序列化并通过postMessage父窗口发送,而不是调用浏览器API WebAuthn
  3. 在父窗口中,我们反序列化这些参数并调用WebAuthn方法;
  4. 当我们收到答案时,我们会以相同的方式对其进行序列化,并通过postMessageiframe内部发送它,我们在其中接受该答案并执行进一步的处理。

因此,我们规避了这一禁令,并意识到了在公司所有服务的授权过程中使用相同密钥的可能性。

WebAuthn测试自动化


在我们针对所有新项目和功能的团队中,我们始终使用类似硒的解决方案和WebDriver协议编写集成UI自动测试。因此,在WebAuthn的开发过程中,出现了如何在其上编写自动测试UI的问题。

编写此类自动测试的困难在于WebDriver协议尚没有用于自动与WebAuthn交互的方法。而且在标准本身中,仍然不支持测试自动化WebAuthn API(但是在此主题上存在问题)。Web身份验证草稿中描述了有关如何组织这种自动化的最初想法:一种用于访问公钥凭据级别2的API,并且尚未发布,更不用说在其他地方得到支持。因此,我不得不提出其他解决方案。

因为 我们无法在自动测试中使用WebAuthn函数的本机实现(没有用于控制浏览器的方法),因此我们必须执行以下操作。

在自动测试的某个位置,尝试使用WebAuthn之前,我们先修补浏览器的全局宿主对象,然后用实现替换本机函数。在这里,我们将调用本地函数的参数保存到变量中,并返回promise。

//    WebAuthn   
navigator.credentials.create = (options) => {
    window.credentialsCreateArgs = options;

    return new Promise((resolve, reject) => {
        window.credentialsCreateSuccess = resolve;
        window.credentialsCreateFail = reject;
    });
};

接下来,我们需要以某种方式获取函数的结果以将其返回以模拟测试中的WebAuthn的工作。我们总是可以返回某种恒定的硬编码答案。

// -    
const credentialsCreateResponse = { /* constant object */ };

window.credentialsCreateSuccess(credentialsCreateResponse);

在这种情况下,我们将必须教我们的服务器接受此答案,而不是对其进行验证,而是认为它会自动纠正。

这样的测试有什么缺点?在这种情况下,我们将无法:

  • 检查客户端是否正确形成参数并将参数滚动到WebAuthn函数中;
  • 在滚动后端版本时检查后端更改的正确性。

因此,这样的测试将不够可靠,这不适合我们。

我们决定采用更困难的方法,结果在Node.js上编写了自己的FIDO2协议和算法的实现,在此方法的帮助下,我们设法将这些功能锁定为尽可能接近本机实现。

也就是说,我们编写了一个函数,该函数根据请求参数计算锁定的WebAuthn函数的响应,以便服务器认为它完全正确。

// -    
const credentialsCreateResponse =
    calcCredentialsCreateResponse(window.credentialsCreateArgs);
 
window.credentialsCreateSuccess(credentialsCreateResponse);

结果,自动测试操作方案如下:

  1. 获取调用WebAuthn方法的参数;
  2. 我们通过一个函数执行这些参数,该函数实现与真实身份验证器内部算法相同的算法;
  3. 我们得到结果,并从替换后的函数返回结果;
  4. 我们服务中的所有其余代码均以常规模式处理这些响应,因此,该服务的所有行为与真实用户的行为没有区别。

这种自动测试的源代码和最隐秘的身份验证器的实现位于github存储库中,您可以稍后开始并研究它们的工作。在编写身份验证器时,我们仅受w3.org规范和Node.js文档的指导。

WebAuthn的现在和未来


因此,我们目前所拥有的。

我们 2019年9月底推出了可正常使用的电子钥匙条目。现在,我们不宣传这种类型的条目,并且使用起来也不是很活跃-每天少于100个唯一用户。但是我们相信,随着时间的流逝,它们的数量只会增加,并且电子钥匙记录早晚会成为登录到您帐户的主要类型之一。

使我们无法积极推广这样的条目的原因是,WebAuthn本身在浏览器中仍然不够可靠和稳定,并且在支持和操作方面存在许多细微差别。

为什么WebAuthn现在不适合广大用户使用?

这里最基本的因素是,它要求用户拥有特殊的设备-电子钥匙。现在,用户对它的需求并不那么迫切。许多用户不知道他们的存在。但是随着时间的流逝,当越来越多的服务开始支持这种登录方式时,具有此类密钥的用户数量也将开始增长。

当Google工程师完成开发和测试使用Android OS和iOS上的智能手机作为WebAuthn的外部物理电子密钥并为所有Internet服务打开这一机会时,WebAuthn的普及将发生重大飞跃。在这种情况下,现代智能手机的每个拥有者实际上都将有机会将其用作WebAuthn密钥,并且WebAuthn用户的数量将急剧增加。现在,这个功能可以只对谷歌电子邮件服务的用户。



您还可以如何使用WebAuthn?


Mail.ru现在使用WebAuthn作为输入帐户密码的替代方法。但是本质上,WebAuthn可以像任何授权因素一样使用。它可以代替单因素身份验证中的第一因素。因此,而不是第二个-作为具有双重保护的附加密码保护。此外,例如,如果用户丢失或忘记了密码,则在恢复对帐户的访问权限时,可以使用通过电子钥匙进行的确认。

在编辑帐户的关键设置时,WebAuthn可以用作其他安全措施。想象一下它有多方便-您可以在自己喜欢的服务中转到个人资料设置,而无需记住并输入密码即可更改它们!只需将手指放在指纹扫描仪上,您就会被传走。

这篇中型文章中,您可以找到更多使用WebAuthn的不同方案

热门问答


在哪里可以买到电子钥匙?


到目前为止,在俄罗斯没有多少地方可以购买与FIDO2协议兼容的电子钥匙。大多数供应商只批量出售10批或更多。您可以在以下商店中逐件购买电子钥匙:


同样,可以在友好的在线商店中(例如,在Amazon上)订购此类密钥本文中,具有电子开关10型号的比较特性,这些型号具有指向可以购买其的商店的链接。

如果我丢失了电子钥匙怎么办?


使用电子钥匙时,应像对待公寓或汽车的钥匙一样对待它们。如果我们丢失了公寓的钥匙,我们通常会更改锁并获取新钥匙。电子钥匙也是如此:如果丢失,则应立即将它们从链接它们的所有帐户中删除,并将新的身份验证器附加到所有帐户。

万一丢失主电子钥匙,您应该有几种其他的认证方法。例如,使用该应用程序生成代码,或者使用备用密钥,该备用密钥可以存储在受特别保护的位置:保险箱或银行单元中。

如果其他人可以访问我的电子钥匙该怎么办?


如果您的帐户中包含双重身份验证,而电子密钥只是其中之一,那么在这种情况下,您的帐户将受到保护,免受黑客攻击。除非攻击者可以使用第二个因素。

如果电子钥匙是足以输入该帐户的唯一因素,那么即使在这种情况下,攻击者也必须知道该电子钥匙在其中注册的帐户的名称。该信息未存储在电子钥匙内部,因此,意外丢失的电子钥匙具有很高的概率,对于找到它的路人来说将完全无用。

但是,存在这样的方案,其中电子钥匙不仅可以代替密码,还可以代替登录。在这种情况下,服务器仅在请求凭据时提供凭据。origin,并且凭据本身完全存储在身份验证器中。在这种情况下,丢失的电子钥匙已经可以很容易地用于输入您的帐户,然后您应该更加注意身份验证器。为了在这种情况下提供保护,您可以使用带有其他安全措施的电子钥匙,例如钥匙,要激活该钥匙,您需要输入PIN码。

无论如何,一旦发现密钥丢失,您应立即将其从所有服务的所有帐户中解开,并可以在其中使用它进行输入。这就是为什么所有服务都应提供管理绑定的身份验证器列表的功能的原因。您注意到丢失的速度越快,攻击者获得访问您的数据所需的时间就越少。

现在,我的生物特征数据将存储在Mail.ru/Google/Microsoft服务器上?


当WebAuthn与内置身份验证器一起使用时(例如,在Mac OS上使用Touch ID),只有相应的传感器和操作系统本身才能访问您的生物识别数据。该Web服务不接收或处理任何生物特征信息;它仅适用于公共密码密钥和使用私钥签名的数据。

并且在服务器本身上,仅存储有关公钥的信息。因此,WebAuthn不会以任何方式使用您的生物识别数据来与内置身份验证器一起使用。

结论


我们发现,与密码相比,WebAuthn具有许多重要的优点:

  • 使用WebAuthn时,不需要记住和输入密码;
  • WebAuthn - , ;
  • WebAuthn ;
  • WebAuthn — .

但是,不应丢弃密码。物理密钥仍然可以像密码一样被盗或丢失。但是密码具有重要的优势。只要它们存储在头部,他们将无法识别它们未经所有者的知识。

总而言之,我想说WebAuthn技术是一种非常有前途的技术,它改变了所有现代Web服务作为身份验证功能的这种基本和重要元素。它也是一种相当年轻的技术,用户尚未习惯。但是,我们有能力使其更加流行和方便。

希望我们在Mail.ru Mail中实现WebAuthn的经验能够帮助您在服务中支持WebAuthn,并且我们共同努力将使Internet更安全,更现代!

附加材料



All Articles