github / webauthn-json

🔏 A small WebAuthn API wrapper that translates to/from pure JSON using base64url.
https://github.github.com/webauthn-json/demo/
MIT License
760 stars 61 forks source link

Write tests using Chrome's virtual authenticator API #31

Open lgarron opened 4 years ago

lgarron commented 4 years ago

I've held off on writing thorough tests, because getting a good mock WebAuthn authenticator working was a bit daunting. However, Chrome's DevTools protocol now supports virtual authenticators: https://chromedevtools.github.io/devtools-protocol/tot/WebAuthn/

This should make it possible to write fairly robust tests.

I haven't set up a GitHub action testing using the DevTools protocol, so we could use some help if anyone is familiar with how to set that up.

halo commented 2 years ago

Using Capybara and the webauthn gem, I was able to get integration tests working in a Rails environment. I thought I'd post it here for a kickstart (which testing-stack are you intending to use, by the way?).

To my surprise, recent versions of selenium/webdrivers support this out-of-the-box.

# Setup is only possible *after* an initial request (visit in Capybara) has been made.
visit '/login'

# Ensure same-origin
WebAuthn.configuration.origin = Capybara.current_session.server.base_url

# Enable virtual authenticators in browser
devtools = page.driver.browser.devtools
devtools.send_cmd 'WebAuthn.enable'

# Create an Authenticator
# See https://chromedevtools.github.io/devtools-protocol/tot/WebAuthn/#type-VirtualAuthenticatorOptions
options = {
  protocol: :ctap2,
  transport: :internal,
  hasResidentKey: false, # Chrome should not have to reveal a list of existing virtual authenticator IDs.
  # isUserConsenting: true, # Not sure, this option exists in selenium but not in chrome?
  hasUserVerification: true,
  isUserVerified: true,
}
attributes = record.devtools.send_cmd 'WebAuthn.addVirtualAuthenticator', options: options
id = attributes.dig('result', 'authenticatorId')

# Make sure to tear down after each test because it will interfere with further tests
devtools.send_cmd 'WebAuthn.removeVirtualAuthenticator', authenticatorId: id
devtools.send_cmd 'WebAuthn.disable'
halo commented 2 years ago

Thanks to this commit it just got much simpler:

visit '/login'

options = ::Selenium::WebDriver::VirtualAuthenticatorOptions.new
page.driver.browser.add_virtual_authenticator(options)

click_on 'Start the registration ceremony using my new hardware key'
lgarron commented 2 years ago

Thanks to this commit it just got much simpler:

Thanks!

Just to be transparent, though: In the interest of keeping this library as easy as possible to maintain for its limited remaining lifetime, I think any JS testing framework would be preferable over Ruby (or over any other separate language).

halo commented 2 years ago

I completely agree, thanks for being clear. I just wanted to post this as a heads-up that selenium is in the progress of directly implementing those DevTools calls. Three months ago JS got them as well. Good luck!