75 lines
2.4 KiB
Ruby
75 lines
2.4 KiB
Ruby
|
# 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
|