2020-11-24 15:15:51 +05:30
|
|
|
# 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
|
2023-06-20 00:43:36 +05:30
|
|
|
@page.click_button(_('Try again?'))
|
2020-11-24 15:15:51 +05:30
|
|
|
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
|