Selenium测试:使用Webauthn进行身份验证

3
在我的使用情况中,有一个注册页面会触发特定于浏览器的Webauthn流程。例如,在Mac上的Chrome浏览器中,您将看到以下一系列弹出窗口:
  1. 在USB安全密钥和内置传感器之间选择选项
  2. 使用Touch ID进行的MacOS确认
  3. Chrome浏览器请求访问您的安全密钥的确认对话框
除了 https://w3c.github.io/webauthn/#add-virtual-authenticator ,我没有找到太多关于在Selenium测试中作为Webauthn身份验证的文档。有哪些资源可用于帮助开发人员学习如何使用JavaScript测试Webauthn?我还查看了https://github.com/SeleniumHQ/selenium/issues/7829,但是示例测试用例对我来说没有意义。提供示例将非常感激。 使用js更新的解决方案:
  import { Command } from 'selenium-webdriver/lib/command';

  addVirtualAuthenticator = async () => {
    await this.driver.getSession().then(async session => {
      this.driver
        .getExecutor()
        .defineCommand('AddVirtualAuthenticator', 'POST', `/session/${session.id_}/webauthn/authenticator`);

      let addVirtualAuthCommand = new Command('AddVirtualAuthenticator');
      addVirtualAuthCommand.setParameter('protocol', 'ctap2');
      addVirtualAuthCommand.setParameter('transport', 'internal');
      addVirtualAuthCommand.setParameter('hasResidentKey', true);
      addVirtualAuthCommand.setParameter('isUserConsenting', true);
      await this.driver.getExecutor().execute(addVirtualAuthCommand);
    });
  };

请注意,this.driver的类型是WebDriver
在执行任何与navigator交互的代码之前调用addVirtualAuthenticator(在我们的情况下,用户注册涉及调用navigator.credentials.create)。如果您需要在登录期间通过navigator.credentials.get({ publicKey: options })访问publicKey,则hasResidentKey至关重要。
2个回答

5
一个很好的Java和Selenium 4实现示例的资源是Selenium自身的测试。基本上你需要:
- 创建一个虚拟认证器。 - 在您的情况下,您应该将传输设置为 internal 并将hasUserVerification设置为 true 以模拟TouchID。
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions();
options.setTransport(Transport.INTERNAL)
       .hasUserVerification(true)
       .isUserVerified(true);
VirtualAuthenticator authenticator =
    ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options);
  • 执行触发注册的操作。

    如果一切正常,浏览器不应该显示对话框。相反,它应立即返回凭据。

对于其他语言或Selenium版本,您需要直接调用WebDriver协议。正如您所指出的,W3C规范在协议端点上有文档说明

对于Java,可能是以下内容:

browser.driver.getExecutor().defineCommand(
    "AddVirtualAuthenticator", "POST", "/session/:sessionId/webauthn/authenticator");

// ...

Command addVirtualAuthCommand = new Command("AddVirtualAuthenticator");
addVirtualAuthCommand.setParameter("protocol", "ctap2");
addVirtualAuthCommand.setParameter("transport", "usb");
browser.driver.getExecutor().execute(addVirtualAuthCommand);

对于JavaScript,您应该能够以类似的方式使用defineCommandwebDriver.execute


1
感谢这个有用的信息!我使用您提供的示例Java代码的JavaScript版本成功地实现了注册。有趣的是,尽管注册成功,但尝试使用新创建的帐户登录失败,指向https://www.w3.org/TR/webauthn-2/#sctn-privacy-considerations-client。我仍在调试中,等我知道更多信息时会更新。再次感谢您的帮助! - mkhbragg
可能是认证器被创建在不同的框架中,而不是您尝试进行断言的那个框架。如果您试图从不同的框架树(例如从另一个浏览器实例或父级iframe)中使用凭据,则会发生这种情况。如果调用GetCredentials命令会发生什么? - Nina Satragno
啊,我能看出那可能是问题所在。从测试中调用GetCredentials返回一个空数组。今天会进一步调查。 - mkhbragg
1
啊哈!在登录时,UI 调用了 navigator.credentials.get({ publicKey: options }),因此为了让虚拟认证器正常工作,我需要包含 addVirtualAuthCommand.setParameter('hasResidentKey', true);。这是一个如此简单的修复,但花费了很长时间才找到。但现在它可以工作了!仍在整理测试结构,一旦满意,我会更新更完整的发现。 - mkhbragg
1
感谢@NinaSatragno在这方面的出色贡献 :) - Saikat

-2

这是Selenium中最糟糕的实践。

两步验证(Two Factor Authentication,简称2FA)是一种授权机制,其中使用“Authenticator”移动应用程序(如“Google Authenticator”,“Microsoft Authenticator”等)或通过短信、电子邮件生成一次性密码(OTP)进行身份验证。在Selenium中无缝且一致地自动化此过程是一个巨大的挑战。有一些方法可以自动化此过程。但那将是我们Selenium测试之上的另一层,并且也不安全。因此,您可以避免自动化2FA。

有几个选项可以绕过2FA检查:

1.在测试环境中为某些用户禁用2FA,以便您可以在自动化中使用这些用户凭据。 2.在测试环境中禁用2FA。 3.如果您从某些IP登录,则禁用2FA。这样,我们可以配置我们的测试机器IP以避免此问题。


这个问题涉及到WebAuthn(而不是认证器应用程序),Selenium 4+支持它。您可能还想将2FA作为E2E套件的一部分进行测试。 - Nina Satragno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接