Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/rb/spec/integration/selenium/webdriver/virtual_authenticator_spec.rb
1864 views
1
# frozen_string_literal: true
2
3
# Licensed to the Software Freedom Conservancy (SFC) under one
4
# or more contributor license agreements. See the NOTICE file
5
# distributed with this work for additional information
6
# regarding copyright ownership. The SFC licenses this file
7
# to you under the Apache License, Version 2.0 (the
8
# "License"); you may not use this file except in compliance
9
# with the License. You may obtain a copy of the License at
10
#
11
# http://www.apache.org/licenses/LICENSE-2.0
12
#
13
# Unless required by applicable law or agreed to in writing,
14
# software distributed under the License is distributed on an
15
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
# KIND, either express or implied. See the License for the
17
# specific language governing permissions and limitations
18
# under the License.
19
20
require_relative 'spec_helper'
21
22
module Selenium
23
module WebDriver
24
describe VirtualAuthenticator, exclusive: [{bidi: false, reason: 'Not yet implemented with BiDi'},
25
{browser: %i[chrome edge]}] do
26
# A pkcs#8 encoded unencrypted EC256 private key as a base64url string.
27
let(:pkcs8_private_key) do
28
'MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q' \
29
'hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU' \
30
'RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB'
31
end
32
let(:encoded_private_key) do
33
'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr' \
34
'MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV' \
35
'oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ' \
36
'FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq' \
37
'GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0' \
38
'+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM' \
39
'8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD' \
40
'/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ' \
41
'5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe' \
42
'pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol' \
43
'L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d' \
44
'xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi' \
45
'uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8' \
46
'K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct' \
47
'lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa' \
48
'9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH' \
49
'zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H' \
50
'BYGpI8g=='
51
end
52
let(:u2f) { VirtualAuthenticatorOptions.new(protocol: :u2f) }
53
let(:ctap2) { VirtualAuthenticatorOptions.new(user_verification: true, user_verified: true) }
54
55
before { driver.navigate.to url_for('virtual-authenticator.html') }
56
57
after { @authenticator&.remove! if @authenticator&.valid? }
58
59
def register_credential(require_resident: false, user_verification: false)
60
params = if require_resident
61
'{authenticatorSelection: {requireResidentKey: true}}'
62
elsif user_verification
63
"{userVerification: 'required'}"
64
else
65
''
66
end
67
driver.execute_async_script "registerCredential(#{params}).then(arguments[arguments.length - 1]);"
68
end
69
70
def credential(id)
71
script = <<~CREDENTIAL
72
getCredential([{
73
"type": "public-key",
74
"id": Int8Array.from(arguments[0]),
75
}]).then(arguments[arguments.length - 1]);
76
CREDENTIAL
77
driver.execute_async_script(script, id)
78
end
79
80
describe '#intialize' do
81
it 'creates resident key disabled u2f' do
82
@authenticator = driver.add_virtual_authenticator(u2f)
83
84
expect(@authenticator.options.protocol).to eq :u2f
85
expect(@authenticator.options.resident_key?).to be false
86
end
87
88
it 'creates resident key enabled u2f' do
89
u2f.resident_key = true
90
@authenticator = driver.add_virtual_authenticator(u2f)
91
92
expect(@authenticator.options.protocol).to eq :u2f
93
expect(@authenticator.options.resident_key?).to be true
94
end
95
96
it 'creates resident key disabled ctap2' do
97
@authenticator = driver.add_virtual_authenticator(ctap2)
98
99
expect(@authenticator.options.protocol).to eq :ctap2
100
expect(@authenticator.options.resident_key?).to be false
101
expect(@authenticator.options.user_verified?).to be true
102
expect(@authenticator.options.user_verification?).to be true
103
end
104
105
it 'creates resident key enabled ctap2' do
106
ctap2.resident_key = true
107
@authenticator = driver.add_virtual_authenticator(ctap2)
108
109
expect(@authenticator.options.protocol).to eq :ctap2
110
expect(@authenticator.options.resident_key?).to be true
111
expect(@authenticator.options.user_verified?).to be true
112
expect(@authenticator.options.user_verification?).to be true
113
end
114
end
115
116
describe '#remove!' do
117
it 'removes authenticator' do
118
@authenticator = driver.add_virtual_authenticator(u2f)
119
120
@authenticator.remove!
121
122
expect(@authenticator.valid?).to be false
123
end
124
end
125
126
describe '#add_credential' do
127
it 'to non-resident ctap' do
128
@authenticator = driver.add_virtual_authenticator(ctap2)
129
130
byte_array_id = [1, 2, 3, 4]
131
credential = Credential.non_resident(id: byte_array_id,
132
rp_id: 'localhost',
133
private_key: Credential.decode(encoded_private_key))
134
135
@authenticator.add_credential(credential)
136
137
expect(credential(byte_array_id)['status']).to eq('OK')
138
end
139
140
it 'to non-resident u2f' do
141
@authenticator = driver.add_virtual_authenticator(u2f)
142
143
byte_array_id = [1, 2, 3, 4]
144
credential = Credential.non_resident(id: byte_array_id,
145
rp_id: 'localhost',
146
private_key: Credential.decode(pkcs8_private_key))
147
148
@authenticator.add_credential(credential)
149
150
expect(credential(byte_array_id)['status']).to eq('OK')
151
end
152
153
it 'to resident ctap' do
154
ctap2.resident_key = true
155
@authenticator = driver.add_virtual_authenticator(ctap2)
156
157
byte_array_id = [1, 2, 3, 4]
158
credential = Credential.resident(id: byte_array_id,
159
rp_id: 'localhost',
160
user_handle: [1],
161
private_key: Credential.decode(encoded_private_key))
162
163
@authenticator.add_credential(credential)
164
165
expect(credential(byte_array_id)['status']).to eq('OK')
166
expect(@authenticator.credentials.first.user_handle).to eq [1]
167
end
168
169
it 'to resident u2f' do
170
u2f.resident_key = true
171
@authenticator = driver.add_virtual_authenticator(u2f)
172
173
byte_array_id = [1, 2, 3, 4]
174
credential = Credential.resident(id: byte_array_id,
175
rp_id: 'localhost',
176
user_handle: [1],
177
private_key: Credential.decode(encoded_private_key))
178
179
msg = /The Authenticator does not support Resident Credentials/
180
expect { @authenticator.add_credential(credential) }.to raise_error(Error::InvalidArgumentError, msg)
181
end
182
end
183
184
describe '#credentials' do
185
it 'gets multiple' do
186
ctap2.resident_key = true
187
@authenticator = driver.add_virtual_authenticator(ctap2)
188
189
# Add multiple credentials with JS
190
res_cred_resp = register_credential(require_resident: true)['credential']
191
non_res_cred_resp = register_credential['credential']
192
expect(res_cred_resp['id']).not_to eq(non_res_cred_resp['id'])
193
194
credentials = @authenticator.credentials
195
expect(credentials.length).to eq(2)
196
197
res_cred_output = credentials.find { |cred| Credential.encode(cred.id).match res_cred_resp['id'] }
198
non_res_cred_output = credentials.find { |cred| cred != res_cred_output }
199
200
expect(res_cred_output.resident_credential?).to be true
201
expect(non_res_cred_output.resident_credential?).to be false
202
end
203
end
204
205
describe '#remove_credential' do
206
it 'by raw ID' do
207
@authenticator = driver.add_virtual_authenticator(u2f)
208
209
credential = register_credential['credential']
210
raw_id = credential['rawId']
211
id = credential['id']
212
2.times { register_credential }
213
214
@authenticator.remove_credential(raw_id)
215
216
expect(@authenticator.credentials.map(&:id)).not_to include(id)
217
end
218
219
it 'by encoded ID' do
220
@authenticator = driver.add_virtual_authenticator(u2f)
221
222
id = register_credential.dig('credential', 'id')
223
2.times { register_credential }
224
225
@authenticator.remove_credential(id)
226
227
expect(@authenticator.credentials.map(&:id)).not_to include(id)
228
end
229
end
230
231
describe '#remove_all_credentials' do
232
it 'removes multiple' do
233
@authenticator = driver.add_virtual_authenticator(u2f)
234
3.times { register_credential }
235
236
@authenticator.remove_all_credentials
237
238
expect(@authenticator.credentials).to be_empty
239
end
240
end
241
242
describe '#user_verified=' do
243
it 'can not obtain credential requiring verification when set to false' do
244
ctap2.resident_key = true
245
@authenticator = driver.add_virtual_authenticator(ctap2)
246
247
raw_id = register_credential(user_verification: true).dig('credential', 'rawId')
248
249
@authenticator.user_verified = false
250
251
expect(credential(raw_id)['status']).to include 'NotAllowedError'
252
end
253
end
254
end # VirtualAuthenticator
255
end # WebDriver
256
end # Selenium
257
258