Path: blob/trunk/rb/spec/integration/selenium/webdriver/virtual_authenticator_spec.rb
1864 views
# frozen_string_literal: true12# Licensed to the Software Freedom Conservancy (SFC) under one3# or more contributor license agreements. See the NOTICE file4# distributed with this work for additional information5# regarding copyright ownership. The SFC licenses this file6# to you under the Apache License, Version 2.0 (the7# "License"); you may not use this file except in compliance8# with the License. You may obtain a copy of the License at9#10# http://www.apache.org/licenses/LICENSE-2.011#12# Unless required by applicable law or agreed to in writing,13# software distributed under the License is distributed on an14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY15# KIND, either express or implied. See the License for the16# specific language governing permissions and limitations17# under the License.1819require_relative 'spec_helper'2021module Selenium22module WebDriver23describe VirtualAuthenticator, exclusive: [{bidi: false, reason: 'Not yet implemented with BiDi'},24{browser: %i[chrome edge]}] do25# A pkcs#8 encoded unencrypted EC256 private key as a base64url string.26let(:pkcs8_private_key) do27'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q' \28'hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU' \29'RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB'30end31let(:encoded_private_key) do32'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr' \33'MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV' \34'oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ' \35'FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq' \36'GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0' \37'+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM' \38'8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD' \39'/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ' \40'5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe' \41'pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol' \42'L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d' \43'xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi' \44'uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8' \45'K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct' \46'lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa' \47'9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH' \48'zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H' \49'BYGpI8g=='50end51let(:u2f) { VirtualAuthenticatorOptions.new(protocol: :u2f) }52let(:ctap2) { VirtualAuthenticatorOptions.new(user_verification: true, user_verified: true) }5354before { driver.navigate.to url_for('virtual-authenticator.html') }5556after { @authenticator&.remove! if @authenticator&.valid? }5758def register_credential(require_resident: false, user_verification: false)59params = if require_resident60'{authenticatorSelection: {requireResidentKey: true}}'61elsif user_verification62"{userVerification: 'required'}"63else64''65end66driver.execute_async_script "registerCredential(#{params}).then(arguments[arguments.length - 1]);"67end6869def credential(id)70script = <<~CREDENTIAL71getCredential([{72"type": "public-key",73"id": Int8Array.from(arguments[0]),74}]).then(arguments[arguments.length - 1]);75CREDENTIAL76driver.execute_async_script(script, id)77end7879describe '#intialize' do80it 'creates resident key disabled u2f' do81@authenticator = driver.add_virtual_authenticator(u2f)8283expect(@authenticator.options.protocol).to eq :u2f84expect(@authenticator.options.resident_key?).to be false85end8687it 'creates resident key enabled u2f' do88u2f.resident_key = true89@authenticator = driver.add_virtual_authenticator(u2f)9091expect(@authenticator.options.protocol).to eq :u2f92expect(@authenticator.options.resident_key?).to be true93end9495it 'creates resident key disabled ctap2' do96@authenticator = driver.add_virtual_authenticator(ctap2)9798expect(@authenticator.options.protocol).to eq :ctap299expect(@authenticator.options.resident_key?).to be false100expect(@authenticator.options.user_verified?).to be true101expect(@authenticator.options.user_verification?).to be true102end103104it 'creates resident key enabled ctap2' do105ctap2.resident_key = true106@authenticator = driver.add_virtual_authenticator(ctap2)107108expect(@authenticator.options.protocol).to eq :ctap2109expect(@authenticator.options.resident_key?).to be true110expect(@authenticator.options.user_verified?).to be true111expect(@authenticator.options.user_verification?).to be true112end113end114115describe '#remove!' do116it 'removes authenticator' do117@authenticator = driver.add_virtual_authenticator(u2f)118119@authenticator.remove!120121expect(@authenticator.valid?).to be false122end123end124125describe '#add_credential' do126it 'to non-resident ctap' do127@authenticator = driver.add_virtual_authenticator(ctap2)128129byte_array_id = [1, 2, 3, 4]130credential = Credential.non_resident(id: byte_array_id,131rp_id: 'localhost',132private_key: Credential.decode(encoded_private_key))133134@authenticator.add_credential(credential)135136expect(credential(byte_array_id)['status']).to eq('OK')137end138139it 'to non-resident u2f' do140@authenticator = driver.add_virtual_authenticator(u2f)141142byte_array_id = [1, 2, 3, 4]143credential = Credential.non_resident(id: byte_array_id,144rp_id: 'localhost',145private_key: Credential.decode(pkcs8_private_key))146147@authenticator.add_credential(credential)148149expect(credential(byte_array_id)['status']).to eq('OK')150end151152it 'to resident ctap' do153ctap2.resident_key = true154@authenticator = driver.add_virtual_authenticator(ctap2)155156byte_array_id = [1, 2, 3, 4]157credential = Credential.resident(id: byte_array_id,158rp_id: 'localhost',159user_handle: [1],160private_key: Credential.decode(encoded_private_key))161162@authenticator.add_credential(credential)163164expect(credential(byte_array_id)['status']).to eq('OK')165expect(@authenticator.credentials.first.user_handle).to eq [1]166end167168it 'to resident u2f' do169u2f.resident_key = true170@authenticator = driver.add_virtual_authenticator(u2f)171172byte_array_id = [1, 2, 3, 4]173credential = Credential.resident(id: byte_array_id,174rp_id: 'localhost',175user_handle: [1],176private_key: Credential.decode(encoded_private_key))177178msg = /The Authenticator does not support Resident Credentials/179expect { @authenticator.add_credential(credential) }.to raise_error(Error::InvalidArgumentError, msg)180end181end182183describe '#credentials' do184it 'gets multiple' do185ctap2.resident_key = true186@authenticator = driver.add_virtual_authenticator(ctap2)187188# Add multiple credentials with JS189res_cred_resp = register_credential(require_resident: true)['credential']190non_res_cred_resp = register_credential['credential']191expect(res_cred_resp['id']).not_to eq(non_res_cred_resp['id'])192193credentials = @authenticator.credentials194expect(credentials.length).to eq(2)195196res_cred_output = credentials.find { |cred| Credential.encode(cred.id).match res_cred_resp['id'] }197non_res_cred_output = credentials.find { |cred| cred != res_cred_output }198199expect(res_cred_output.resident_credential?).to be true200expect(non_res_cred_output.resident_credential?).to be false201end202end203204describe '#remove_credential' do205it 'by raw ID' do206@authenticator = driver.add_virtual_authenticator(u2f)207208credential = register_credential['credential']209raw_id = credential['rawId']210id = credential['id']2112.times { register_credential }212213@authenticator.remove_credential(raw_id)214215expect(@authenticator.credentials.map(&:id)).not_to include(id)216end217218it 'by encoded ID' do219@authenticator = driver.add_virtual_authenticator(u2f)220221id = register_credential.dig('credential', 'id')2222.times { register_credential }223224@authenticator.remove_credential(id)225226expect(@authenticator.credentials.map(&:id)).not_to include(id)227end228end229230describe '#remove_all_credentials' do231it 'removes multiple' do232@authenticator = driver.add_virtual_authenticator(u2f)2333.times { register_credential }234235@authenticator.remove_all_credentials236237expect(@authenticator.credentials).to be_empty238end239end240241describe '#user_verified=' do242it 'can not obtain credential requiring verification when set to false' do243ctap2.resident_key = true244@authenticator = driver.add_virtual_authenticator(ctap2)245246raw_id = register_credential(user_verification: true).dig('credential', 'rawId')247248@authenticator.user_verified = false249250expect(credential(raw_id)['status']).to include 'NotAllowedError'251end252end253end # VirtualAuthenticator254end # WebDriver255end # Selenium256257258