diff options
Diffstat (limited to 'spec/support/helpers/fake_webauthn_device.rb')
-rw-r--r-- | spec/support/helpers/fake_webauthn_device.rb | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/spec/support/helpers/fake_webauthn_device.rb b/spec/support/helpers/fake_webauthn_device.rb new file mode 100644 index 00000000000..d2c2f7d6bf3 --- /dev/null +++ b/spec/support/helpers/fake_webauthn_device.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true +require 'webauthn/fake_client' + +class FakeWebauthnDevice + attr_reader :name + + def initialize(page, name, device = nil) + @page = page + @name = name + @webauthn_device = device + end + + def respond_to_webauthn_registration + app_id = @page.evaluate_script('gon.webauthn.app_id') + challenge = @page.evaluate_script('gon.webauthn.options.challenge') + + json_response = webauthn_device(app_id).create(challenge: challenge).to_json # rubocop:disable Rails/SaveBang + @page.execute_script <<~JS + var result = #{json_response}; + result.getClientExtensionResults = () => ({}); + navigator.credentials.create = function(_) { + return Promise.resolve(result); + }; + JS + end + + def respond_to_webauthn_authentication + app_id = @page.evaluate_script('JSON.parse(gon.webauthn.options).extensions.appid') + challenge = @page.evaluate_script('JSON.parse(gon.webauthn.options).challenge') + + begin + json_response = webauthn_device(app_id).get(challenge: challenge).to_json + + rescue RuntimeError + # A runtime error is raised from fake webauthn if no credentials have been registered yet. + # To be able to test non registered devices, credentials are created ad-hoc + webauthn_device(app_id).create # rubocop:disable Rails/SaveBang + json_response = webauthn_device(app_id).get(challenge: challenge).to_json + end + + @page.execute_script <<~JS + var result = #{json_response}; + result.getClientExtensionResults = () => ({}); + navigator.credentials.get = function(_) { + return Promise.resolve(result); + }; + JS + @page.click_link('Try again?', href: false) + end + + def fake_webauthn_authentication + @page.execute_script <<~JS + const mockResponse = { + type: 'public-key', + id: '', + rawId: '', + response: { clientDataJSON: '', authenticatorData: '', signature: '', userHandle: '' }, + getClientExtensionResults: () => {}, + }; + window.gl.resolveWebauthn(mockResponse); + JS + end + + def add_credential(app_id, credential_id, credential_key) + credentials = { URI.parse(app_id).host => { credential_id => { credential_key: credential_key, sign_count: 0 } } } + webauthn_device(app_id).send(:authenticator).instance_variable_set(:@credentials, credentials) + end + + private + + def webauthn_device(app_id) + @webauthn_device ||= WebAuthn::FakeClient.new(app_id) + end +end |