且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-12-04 21:27:58

一个很好的示例资源,如果你在 java 中实现它并使用 selenium 4 是 selenium 本身的测试.你基本上需要

  • 创建虚拟身份验证器

    在您的情况下,您应该将传输设置为 internal 并将 hasUserVerification 设置为 true 以模拟 touchID.

VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions();options.setTransport(Transport.INTERNAL).hasUserVerification(真).isUserVerified(true);VirtualAuthenticator 验证器 =((HasVirtualAuthenticator) 驱动程序).addVirtualAuthenticator(options);

  • 执行触发注册的操作.

    如果一切顺利,浏览器不应显示对话框.相反,它应该立即返回一个凭证.

对于任何其他语言或 selenium 版本,您需要直接调用 WebDriver 协议.正如您所指出的,W3C 规范有关于协议端点的文档.>

对于java,它可能类似于

browser.driver.getExecutor().defineCommand(AddVirtualAuthenticator"、POST"、/session/:sessionId/webauthn/authenticator");//...命令 addVirtualAuthCommand = new Command(AddVirtualAuthenticator");addVirtualAuthCommand.setParameter("protocol", "ctap2");addVirtualAuthCommand.setParameter("transport", "usb");browser.driver.getExecutor().execute(addVirtualAuthCommand);

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

In my use case, there is a registration page that triggers the browser-specific webauthn flow. For example in Chrome on a Mac you will see this series of popups:

  1. Pick an option between USB security key and Built-in sensor
  2. MacOS confirmation with Touch ID
  3. Confirmation dialog from Chrome requesting access to your security key

Besides https://w3c.github.io/webauthn/#add-virtual-authenticator I haven't found much documentation about authenticating with webauthn as part of a selenium test. What resources are available to help devs figure out how to test webauthn with Selenium in JavaScript? I have also checked out https://github.com/SeleniumHQ/selenium/issues/7829 but the example test case does not make sense to me. Examples would be hugely appreciated.

Update with solution for 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);
    });
  };

Note that this.driver is of type WebDriver.

Call addVirtualAuthenticator before hitting any code that interacts with navigator (in our case user registration involved a call to navigator.credentials.create). If you need access to the publicKey, i.e. via navigator.credentials.get({ publicKey: options }) during login, then hasResidentKey is critical.

A good resource for an example if you're implementing this in java and using selenium 4 is the tests on selenium itself. You basically need to

  • Create a virtual authenticator

    In your case, you should set the transport to internal and hasUserVerification to true to simulate touchID.

VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions();
options.setTransport(Transport.INTERNAL)
       .hasUserVerification(true)
       .isUserVerified(true);
VirtualAuthenticator authenticator =
    ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options);

  • Perform the action that triggers registration.

    If everything goes right, the browser should not show a dialog. Instead, it should immediately return a credential.

For any other language or selenium version, you will need to drop into calling the WebDriver protocol directly. As you pointed out, the W3C spec has documentation on the protocol endpoints.

For java, it might be something like

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);

For javascript, you should be able to use defineCommand and webDriver.execute in a similar fashion.