blob: 30391c3d161f135b3a0400814e5a3a5fab877de6 [file] [log] [blame]
Jun Choi4fc8b7812018-04-05 07:39:071// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <memory>
6#include <utility>
7
Balazs Engedy159452d2018-08-16 15:18:188#include "base/bind.h"
9#include "base/bind_helpers.h"
Martin Kreichgauerdf06312d2018-11-08 00:43:3610#include "base/stl_util.h"
Jun Choi0e56e5dd2018-06-08 21:27:3411#include "base/test/scoped_feature_list.h"
Jun Choi4fc8b7812018-04-05 07:39:0712#include "base/test/scoped_task_environment.h"
Martin Kreichgauerdf06312d2018-11-08 00:43:3613#include "build/build_config.h"
Jun Choi0e56e5dd2018-06-08 21:27:3414#include "device/base/features.h"
Jun Choife176682018-08-30 07:49:1415#include "device/bluetooth/bluetooth_adapter_factory.h"
16#include "device/bluetooth/test/mock_bluetooth_adapter.h"
Jun Choi4fc8b7812018-04-05 07:39:0717#include "device/fido/authenticator_get_assertion_response.h"
18#include "device/fido/ctap_get_assertion_request.h"
Balazs Engedy159452d2018-08-16 15:18:1819#include "device/fido/device_response_converter.h"
Jun Choi4fc8b7812018-04-05 07:39:0720#include "device/fido/fake_fido_discovery.h"
Martin Kreichgauerdf06312d2018-11-08 00:43:3621#include "device/fido/features.h"
Jun Choi4fc8b7812018-04-05 07:39:0722#include "device/fido/fido_constants.h"
Jun Choi19b944e92018-04-23 20:20:2023#include "device/fido/fido_parsing_utils.h"
Jun Choi22af8b372018-04-09 04:29:1824#include "device/fido/fido_test_data.h"
Jun Choib60937e2018-04-12 17:02:3825#include "device/fido/fido_transport_protocol.h"
Jun Choi4fc8b7812018-04-05 07:39:0726#include "device/fido/get_assertion_request_handler.h"
Martin Kreichgauerdf06312d2018-11-08 00:43:3627#include "device/fido/hid/fake_hid_impl_for_testing.h"
Jun Choi4fc8b7812018-04-05 07:39:0728#include "device/fido/mock_fido_device.h"
29#include "device/fido/test_callback_receiver.h"
Jun Choi4fc8b7812018-04-05 07:39:0730#include "testing/gmock/include/gmock/gmock.h"
31#include "testing/gtest/include/gtest/gtest.h"
32
Martin Kreichgauer75377812018-11-09 18:58:1333#if defined(OS_WIN)
Martin Kreichgauerb129ae52018-11-14 21:26:3334#include "device/fido/win/authenticator.h"
Martin Kreichgauerdf06312d2018-11-08 00:43:3635#include "device/fido/win/fake_webauthn_api.h"
Martin Kreichgauer75377812018-11-09 18:58:1336#endif // defined(OS_WIN)
Martin Kreichgauerdf06312d2018-11-08 00:43:3637
Jun Choi4fc8b7812018-04-05 07:39:0738namespace device {
39
40namespace {
41
Balazs Engedy159452d2018-08-16 15:18:1842constexpr uint8_t kBogusCredentialId[] = {0x01, 0x02, 0x03, 0x04};
43
Jun Choi1beb4c22018-08-16 03:04:3844using TestGetAssertionRequestCallback = test::StatusAndValuesCallbackReceiver<
Jun Choif7ab0df2018-04-05 21:48:1645 FidoReturnCode,
Jun Choi1beb4c22018-08-16 03:04:3846 base::Optional<AuthenticatorGetAssertionResponse>,
Martin Kreichgauerc6de3bc2018-11-13 03:14:0047 base::Optional<FidoTransportProtocol>>;
Jun Choi4fc8b7812018-04-05 07:39:0748
49} // namespace
50
51class FidoGetAssertionHandlerTest : public ::testing::Test {
52 public:
Jun Choife176682018-08-30 07:49:1453 FidoGetAssertionHandlerTest() {
54 mock_adapter_ =
55 base::MakeRefCounted<::testing::NiceMock<MockBluetoothAdapter>>();
56 BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_);
57 }
58
Balazs Engedy159452d2018-08-16 15:18:1859 void ForgeDiscoveries() {
Jun Choi4fc8b7812018-04-05 07:39:0760 discovery_ = scoped_fake_discovery_factory_.ForgeNextHidDiscovery();
Balazs Engedy159452d2018-08-16 15:18:1861 ble_discovery_ = scoped_fake_discovery_factory_.ForgeNextBleDiscovery();
Balazs Engedy5b4891f2018-08-29 23:08:0062 cable_discovery_ = scoped_fake_discovery_factory_.ForgeNextCableDiscovery();
Balazs Engedy159452d2018-08-16 15:18:1863 nfc_discovery_ = scoped_fake_discovery_factory_.ForgeNextNfcDiscovery();
Jun Choi4fc8b7812018-04-05 07:39:0764 }
65
Balazs Engedy5b4891f2018-08-29 23:08:0066 CtapGetAssertionRequest CreateTestRequestWithCableExtension() {
67 CtapGetAssertionRequest request(test_data::kRelyingPartyId,
Martin Kreichgauer90c625742018-10-31 04:24:1568 test_data::kClientDataJson);
Balazs Engedy5b4891f2018-08-29 23:08:0069 request.SetCableExtension({});
70 return request;
71 }
72
Martin Kreichgauer8987fd02018-07-20 22:42:0373 std::unique_ptr<GetAssertionRequestHandler> CreateGetAssertionHandlerU2f() {
Martin Kreichgauer2b753722018-07-17 01:06:0174 CtapGetAssertionRequest request(test_data::kRelyingPartyId,
Martin Kreichgauer90c625742018-10-31 04:24:1575 test_data::kClientDataJson);
Martin Kreichgauer2b753722018-07-17 01:06:0176 request.SetAllowList(
Jan Wilken Doerrie726e197e2018-05-14 12:53:2577 {{CredentialType::kPublicKey,
Jun Choi0e56e5dd2018-06-08 21:27:3478 fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
Martin Kreichgauer8987fd02018-07-20 22:42:0379 return CreateGetAssertionHandlerWithRequest(std::move(request));
80 }
Jun Choi4fc8b7812018-04-05 07:39:0781
Martin Kreichgauer8987fd02018-07-20 22:42:0382 std::unique_ptr<GetAssertionRequestHandler> CreateGetAssertionHandlerCtap() {
83 CtapGetAssertionRequest request(test_data::kRelyingPartyId,
Martin Kreichgauer90c625742018-10-31 04:24:1584 test_data::kClientDataJson);
Martin Kreichgauer8987fd02018-07-20 22:42:0385 request.SetAllowList({{CredentialType::kPublicKey,
86 fido_parsing_utils::Materialize(
87 test_data::kTestGetAssertionCredentialId)}});
Martin Kreichgauer2b753722018-07-17 01:06:0188 return CreateGetAssertionHandlerWithRequest(std::move(request));
89 }
90
91 std::unique_ptr<GetAssertionRequestHandler>
92 CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest request) {
Balazs Engedy159452d2018-08-16 15:18:1893 ForgeDiscoveries();
Martin Kreichgauer2b753722018-07-17 01:06:0194
Martin Kreichgauer7cbada432018-08-18 02:30:1495 auto handler = std::make_unique<GetAssertionRequestHandler>(
Balazs Engedy159452d2018-08-16 15:18:1896 nullptr /* connector */, supported_transports_, std::move(request),
Martin Kreichgauer7cbada432018-08-18 02:30:1497 get_assertion_cb_.callback());
98 handler->SetPlatformAuthenticatorOrMarkUnavailable(
99 CreatePlatformAuthenticator());
100 return handler;
Balazs Engedy159452d2018-08-16 15:18:18101 }
102
103 void ExpectAllowedTransportsForRequestAre(
104 GetAssertionRequestHandler* request_handler,
105 base::flat_set<FidoTransportProtocol> transports) {
106 using Transport = FidoTransportProtocol;
107 if (base::ContainsKey(transports, Transport::kUsbHumanInterfaceDevice))
108 discovery()->WaitForCallToStartAndSimulateSuccess();
109 if (base::ContainsKey(transports, Transport::kBluetoothLowEnergy))
110 ble_discovery()->WaitForCallToStartAndSimulateSuccess();
Balazs Engedy5b4891f2018-08-29 23:08:00111 if (base::ContainsKey(transports,
112 Transport::kCloudAssistedBluetoothLowEnergy))
113 cable_discovery()->WaitForCallToStartAndSimulateSuccess();
Balazs Engedy159452d2018-08-16 15:18:18114 if (base::ContainsKey(transports, Transport::kNearFieldCommunication))
115 nfc_discovery()->WaitForCallToStartAndSimulateSuccess();
Balazs Engedy159452d2018-08-16 15:18:18116
117 scoped_task_environment_.FastForwardUntilNoTasksRemain();
118 EXPECT_FALSE(get_assertion_callback().was_called());
119
120 if (!base::ContainsKey(transports, Transport::kUsbHumanInterfaceDevice))
121 EXPECT_FALSE(discovery()->is_start_requested());
122 if (!base::ContainsKey(transports, Transport::kBluetoothLowEnergy))
123 EXPECT_FALSE(ble_discovery()->is_start_requested());
Balazs Engedy5b4891f2018-08-29 23:08:00124 if (!base::ContainsKey(transports,
125 Transport::kCloudAssistedBluetoothLowEnergy))
126 EXPECT_FALSE(cable_discovery()->is_start_requested());
Balazs Engedy159452d2018-08-16 15:18:18127 if (!base::ContainsKey(transports, Transport::kNearFieldCommunication))
128 EXPECT_FALSE(nfc_discovery()->is_start_requested());
Balazs Engedy159452d2018-08-16 15:18:18129
130 // Even with FidoTransportProtocol::kInternal allowed, unless the platform
131 // authenticator factory returns a FidoAuthenticator instance (which it will
132 // not be default), the transport will be marked `unavailable`.
133 transports.erase(Transport::kInternal);
134
135 EXPECT_THAT(
136 request_handler->transport_availability_info().available_transports,
137 ::testing::UnorderedElementsAreArray(transports));
138 }
139
140 void ExpectAllTransportsAreAllowedForRequest(
141 GetAssertionRequestHandler* request_handler) {
142 ExpectAllowedTransportsForRequestAre(request_handler,
Balazs Engedy5b4891f2018-08-29 23:08:00143 GetAllTransportProtocols());
Jun Choi4fc8b7812018-04-05 07:39:07144 }
145
Jun Choid19453d2018-06-21 23:16:39146 void InitFeatureListAndDisableCtapFlag() {
147 scoped_feature_list_.InitAndDisableFeature(kNewCtap2Device);
Jun Choi0e56e5dd2018-06-08 21:27:34148 }
Jun Choi4fc8b7812018-04-05 07:39:07149
Jun Choi0e56e5dd2018-06-08 21:27:34150 test::FakeFidoDiscovery* discovery() const { return discovery_; }
Balazs Engedy159452d2018-08-16 15:18:18151 test::FakeFidoDiscovery* ble_discovery() const { return ble_discovery_; }
Balazs Engedy5b4891f2018-08-29 23:08:00152 test::FakeFidoDiscovery* cable_discovery() const { return cable_discovery_; }
Balazs Engedy159452d2018-08-16 15:18:18153 test::FakeFidoDiscovery* nfc_discovery() const { return nfc_discovery_; }
Jun Choi4fc8b7812018-04-05 07:39:07154 TestGetAssertionRequestCallback& get_assertion_callback() {
155 return get_assertion_cb_;
156 }
157
Balazs Engedy159452d2018-08-16 15:18:18158 void set_mock_platform_device(std::unique_ptr<MockFidoDevice> device) {
Martin Kreichgauer71a36322018-10-09 02:11:38159 pending_mock_platform_device_ = std::move(device);
Balazs Engedy159452d2018-08-16 15:18:18160 }
161
Balazs Engedy159452d2018-08-16 15:18:18162 void set_supported_transports(
163 base::flat_set<FidoTransportProtocol> transports) {
164 supported_transports_ = std::move(transports);
165 }
166
Jun Choi4fc8b7812018-04-05 07:39:07167 protected:
Martin Kreichgauere1223082018-08-20 23:17:38168 base::Optional<PlatformAuthenticatorInfo> CreatePlatformAuthenticator() {
Martin Kreichgauer71a36322018-10-09 02:11:38169 if (!pending_mock_platform_device_)
Martin Kreichgauere1223082018-08-20 23:17:38170 return base::nullopt;
171 return PlatformAuthenticatorInfo(
Martin Kreichgauer71a36322018-10-09 02:11:38172 std::make_unique<FidoDeviceAuthenticator>(
173 std::move(pending_mock_platform_device_)),
Martin Kreichgauere1223082018-08-20 23:17:38174 false /* has_recognized_mac_touch_id_credential_available */);
Balazs Engedy159452d2018-08-16 15:18:18175 }
176
Jun Choi4fc8b7812018-04-05 07:39:07177 base::test::ScopedTaskEnvironment scoped_task_environment_{
178 base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
Jun Choi0e56e5dd2018-06-08 21:27:34179 base::test::ScopedFeatureList scoped_feature_list_;
Jun Choi4fc8b7812018-04-05 07:39:07180 test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
181 test::FakeFidoDiscovery* discovery_;
Balazs Engedy159452d2018-08-16 15:18:18182 test::FakeFidoDiscovery* ble_discovery_;
Balazs Engedy5b4891f2018-08-29 23:08:00183 test::FakeFidoDiscovery* cable_discovery_;
Balazs Engedy159452d2018-08-16 15:18:18184 test::FakeFidoDiscovery* nfc_discovery_;
Jun Choife176682018-08-30 07:49:14185 scoped_refptr<::testing::NiceMock<MockBluetoothAdapter>> mock_adapter_;
Martin Kreichgauer71a36322018-10-09 02:11:38186 std::unique_ptr<MockFidoDevice> pending_mock_platform_device_;
Jun Choi4fc8b7812018-04-05 07:39:07187 TestGetAssertionRequestCallback get_assertion_cb_;
Balazs Engedy159452d2018-08-16 15:18:18188 base::flat_set<FidoTransportProtocol> supported_transports_ =
Balazs Engedy5b4891f2018-08-29 23:08:00189 GetAllTransportProtocols();
Jun Choi4fc8b7812018-04-05 07:39:07190};
191
Balazs Engedy0c4fdc52018-08-20 19:15:28192TEST_F(FidoGetAssertionHandlerTest, TransportAvailabilityInfo) {
193 auto request_handler =
194 CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest(
Martin Kreichgauer90c625742018-10-31 04:24:15195 test_data::kRelyingPartyId, test_data::kClientDataJson));
Balazs Engedy0c4fdc52018-08-20 19:15:28196
197 EXPECT_EQ(FidoRequestHandlerBase::RequestType::kGetAssertion,
198 request_handler->transport_availability_info().request_type);
199 EXPECT_EQ(test_data::kRelyingPartyId,
200 request_handler->transport_availability_info().rp_id);
201}
202
Martin Kreichgauer8987fd02018-07-20 22:42:03203TEST_F(FidoGetAssertionHandlerTest, CtapRequestOnSingleDevice) {
204 auto request_handler = CreateGetAssertionHandlerCtap();
Jun Choi4fc8b7812018-04-05 07:39:07205 discovery()->WaitForCallToStartAndSimulateSuccess();
Martin Kreichgauer8987fd02018-07-20 22:42:03206 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
Jun Choi4fc8b7812018-04-05 07:39:07207 device->ExpectCtap2CommandAndRespondWith(
208 CtapRequestCommand::kAuthenticatorGetAssertion,
209 test_data::kTestGetAssertionResponse);
210
211 discovery()->AddDevice(std::move(device));
212 get_assertion_callback().WaitForCallback();
213
214 EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
Jun Choi1beb4c22018-08-16 03:04:38215 EXPECT_TRUE(get_assertion_callback().value<0>());
Jun Choi4fc8b7812018-04-05 07:39:07216 EXPECT_TRUE(request_handler->is_complete());
217}
218
Jun Choi0e56e5dd2018-06-08 21:27:34219// Test a scenario where the connected authenticator is a U2F device.
220TEST_F(FidoGetAssertionHandlerTest, TestU2fSign) {
Martin Kreichgauer8987fd02018-07-20 22:42:03221 auto request_handler = CreateGetAssertionHandlerU2f();
Jun Choi4fc8b7812018-04-05 07:39:07222 discovery()->WaitForCallToStartAndSimulateSuccess();
223
Martin Kreichgauer8987fd02018-07-20 22:42:03224 auto device = MockFidoDevice::MakeU2fWithGetInfoExpectation();
Jun Choi0e56e5dd2018-06-08 21:27:34225 device->ExpectRequestAndRespondWith(
226 test_data::kU2fCheckOnlySignCommandApdu,
227 test_data::kApduEncodedNoErrorSignResponse);
228 device->ExpectRequestAndRespondWith(
229 test_data::kU2fSignCommandApdu,
230 test_data::kApduEncodedNoErrorSignResponse);
Jun Choi4fc8b7812018-04-05 07:39:07231
232 discovery()->AddDevice(std::move(device));
233 scoped_task_environment_.FastForwardUntilNoTasksRemain();
Jun Choi0e56e5dd2018-06-08 21:27:34234 EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
Jun Choi1beb4c22018-08-16 03:04:38235 EXPECT_TRUE(get_assertion_callback().value<0>());
Jun Choi0e56e5dd2018-06-08 21:27:34236 EXPECT_TRUE(request_handler->is_complete());
237}
238
239// Test a scenario where the connected authenticator is a U2F device and
240// "WebAuthenticationCtap2" flag is not enabled.
241TEST_F(FidoGetAssertionHandlerTest, TestU2fSignWithoutCtapFlag) {
Jun Choid19453d2018-06-21 23:16:39242 InitFeatureListAndDisableCtapFlag();
Martin Kreichgauer8987fd02018-07-20 22:42:03243 auto request_handler = CreateGetAssertionHandlerU2f();
Jun Choi0e56e5dd2018-06-08 21:27:34244 discovery()->WaitForCallToStartAndSimulateSuccess();
245
246 auto device = std::make_unique<MockFidoDevice>();
247 EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
248 device->ExpectRequestAndRespondWith(
249 test_data::kU2fCheckOnlySignCommandApdu,
250 test_data::kApduEncodedNoErrorSignResponse);
251 device->ExpectRequestAndRespondWith(
252 test_data::kU2fSignCommandApdu,
253 test_data::kApduEncodedNoErrorSignResponse);
254
255 discovery()->AddDevice(std::move(device));
256 scoped_task_environment_.FastForwardUntilNoTasksRemain();
257 EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
Jun Choi1beb4c22018-08-16 03:04:38258 EXPECT_TRUE(get_assertion_callback().value<0>());
Jun Choi0e56e5dd2018-06-08 21:27:34259 EXPECT_TRUE(request_handler->is_complete());
Jun Choi4fc8b7812018-04-05 07:39:07260}
261
Martin Kreichgauer2b753722018-07-17 01:06:01262TEST_F(FidoGetAssertionHandlerTest, TestIncompatibleUserVerificationSetting) {
263 auto request = CtapGetAssertionRequest(test_data::kRelyingPartyId,
Martin Kreichgauer90c625742018-10-31 04:24:15264 test_data::kClientDataJson);
Martin Kreichgauer2b753722018-07-17 01:06:01265 request.SetUserVerification(UserVerificationRequirement::kRequired);
266 auto request_handler =
267 CreateGetAssertionHandlerWithRequest(std::move(request));
268 discovery()->WaitForCallToStartAndSimulateSuccess();
269
Martin Kreichgauer8987fd02018-07-20 22:42:03270 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(
Martin Kreichgauer2b753722018-07-17 01:06:01271 test_data::kTestGetInfoResponseWithoutUvSupport);
272
273 discovery()->AddDevice(std::move(device));
274
275 scoped_task_environment_.FastForwardUntilNoTasksRemain();
276 EXPECT_FALSE(get_assertion_callback().was_called());
277}
278
279TEST_F(FidoGetAssertionHandlerTest,
280 TestU2fSignRequestWithUserVerificationRequired) {
281 auto request = CtapGetAssertionRequest(test_data::kRelyingPartyId,
Martin Kreichgauer90c625742018-10-31 04:24:15282 test_data::kClientDataJson);
Martin Kreichgauer2b753722018-07-17 01:06:01283 request.SetAllowList(
284 {{CredentialType::kPublicKey,
285 fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
286 request.SetUserVerification(UserVerificationRequirement::kRequired);
287 auto request_handler =
288 CreateGetAssertionHandlerWithRequest(std::move(request));
289 discovery()->WaitForCallToStartAndSimulateSuccess();
290
Martin Kreichgauer8987fd02018-07-20 22:42:03291 auto device = MockFidoDevice::MakeU2fWithGetInfoExpectation();
292 discovery()->AddDevice(std::move(device));
293
294 scoped_task_environment_.FastForwardUntilNoTasksRemain();
295 EXPECT_FALSE(get_assertion_callback().was_called());
296}
297
298TEST_F(FidoGetAssertionHandlerTest, IncorrectRpIdHash) {
299 auto request_handler =
300 CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest(
Martin Kreichgauer90c625742018-10-31 04:24:15301 test_data::kRelyingPartyId, test_data::kClientDataJson));
Martin Kreichgauer8987fd02018-07-20 22:42:03302 discovery()->WaitForCallToStartAndSimulateSuccess();
303 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
Martin Kreichgauer2b753722018-07-17 01:06:01304 device->ExpectCtap2CommandAndRespondWith(
Martin Kreichgauer8987fd02018-07-20 22:42:03305 CtapRequestCommand::kAuthenticatorGetAssertion,
306 test_data::kTestGetAssertionResponseWithIncorrectRpIdHash);
307
308 discovery()->AddDevice(std::move(device));
309
310 scoped_task_environment_.FastForwardUntilNoTasksRemain();
311 EXPECT_FALSE(get_assertion_callback().was_called());
312}
313
314// Tests a scenario where the authenticator responds with credential ID that
315// is not included in the allowed list.
316TEST_F(FidoGetAssertionHandlerTest, InvalidCredential) {
317 CtapGetAssertionRequest request(test_data::kRelyingPartyId,
Martin Kreichgauer90c625742018-10-31 04:24:15318 test_data::kClientDataJson);
Martin Kreichgauer8987fd02018-07-20 22:42:03319 request.SetAllowList(
320 {{CredentialType::kPublicKey,
321 fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha)}});
322 auto request_handler =
323 CreateGetAssertionHandlerWithRequest(std::move(request));
324 discovery()->WaitForCallToStartAndSimulateSuccess();
325 // Resident Keys must be disabled, otherwise allow list check is skipped.
326 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(
327 test_data::kTestGetInfoResponseWithoutResidentKeySupport);
328 device->ExpectCtap2CommandAndRespondWith(
329 CtapRequestCommand::kAuthenticatorGetAssertion,
330 test_data::kTestGetAssertionResponse);
331
332 discovery()->AddDevice(std::move(device));
333
334 scoped_task_environment_.FastForwardUntilNoTasksRemain();
335 EXPECT_FALSE(get_assertion_callback().was_called());
336}
337
Jun Choib9499af2018-11-07 07:43:51338// Tests a scenario where the authenticator responds with an empty credential.
339// When GetAssertion request only has a single credential in the allow list,
340// this is a valid response. Check that credential is set by the client before
341// the response is returned to the relying party.
342TEST_F(FidoGetAssertionHandlerTest, ValidEmptyCredential) {
343 auto request_handler = CreateGetAssertionHandlerCtap();
344 discovery()->WaitForCallToStartAndSimulateSuccess();
345 // Resident Keys must be disabled, otherwise allow list check is skipped.
346 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(
347 test_data::kTestGetInfoResponseWithoutResidentKeySupport);
348 device->ExpectCtap2CommandAndRespondWith(
349 CtapRequestCommand::kAuthenticatorGetAssertion,
350 test_data::kTestGetAssertionResponseWithEmptyCredential);
351 discovery()->AddDevice(std::move(device));
352
353 get_assertion_callback().WaitForCallback();
354 const auto& response = get_assertion_callback().value<0>();
355 EXPECT_TRUE(request_handler->is_complete());
356 EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
357 ASSERT_TRUE(response);
358 EXPECT_TRUE(response->credential());
359 EXPECT_THAT(
360 response->raw_credential_id(),
361 ::testing::ElementsAreArray(test_data::kTestGetAssertionCredentialId));
362}
363
Martin Kreichgauer8987fd02018-07-20 22:42:03364// Tests a scenario where authenticator responds without user entity in its
365// response but client is expecting a resident key credential.
366TEST_F(FidoGetAssertionHandlerTest, IncorrectUserEntity) {
367 // Use a GetAssertion request with an empty allow list.
368 auto request_handler =
369 CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest(
Martin Kreichgauer90c625742018-10-31 04:24:15370 test_data::kRelyingPartyId, test_data::kClientDataJson));
Martin Kreichgauer8987fd02018-07-20 22:42:03371 discovery()->WaitForCallToStartAndSimulateSuccess();
372 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
373 device->ExpectCtap2CommandAndRespondWith(
374 CtapRequestCommand::kAuthenticatorGetAssertion,
375 test_data::kTestGetAssertionResponse);
Martin Kreichgauer2b753722018-07-17 01:06:01376
377 discovery()->AddDevice(std::move(device));
378
379 scoped_task_environment_.FastForwardUntilNoTasksRemain();
380 EXPECT_FALSE(get_assertion_callback().was_called());
381}
382
Balazs Engedy159452d2018-08-16 15:18:18383TEST_F(FidoGetAssertionHandlerTest,
384 AllTransportsAllowedIfAllowCredentialsListUndefined) {
Balazs Engedy5b4891f2018-08-29 23:08:00385 auto request = CreateTestRequestWithCableExtension();
Jun Choife176682018-08-30 07:49:14386 EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
Balazs Engedy159452d2018-08-16 15:18:18387 auto request_handler =
Balazs Engedy5b4891f2018-08-29 23:08:00388 CreateGetAssertionHandlerWithRequest(std::move(request));
Balazs Engedy159452d2018-08-16 15:18:18389 ExpectAllTransportsAreAllowedForRequest(request_handler.get());
390}
391
392TEST_F(FidoGetAssertionHandlerTest,
393 AllTransportsAllowedIfAllowCredentialsListIsEmpty) {
Balazs Engedy5b4891f2018-08-29 23:08:00394 auto request = CreateTestRequestWithCableExtension();
Balazs Engedy159452d2018-08-16 15:18:18395 request.SetAllowList({});
Jun Choife176682018-08-30 07:49:14396 EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
Balazs Engedy159452d2018-08-16 15:18:18397 auto request_handler =
398 CreateGetAssertionHandlerWithRequest(std::move(request));
399 ExpectAllTransportsAreAllowedForRequest(request_handler.get());
400}
401
402TEST_F(FidoGetAssertionHandlerTest,
403 AllTransportsAllowedIfHasAllowedCredentialWithEmptyTransportsList) {
Balazs Engedy5b4891f2018-08-29 23:08:00404 auto request = CreateTestRequestWithCableExtension();
Balazs Engedy159452d2018-08-16 15:18:18405 request.SetAllowList({
406 {CredentialType::kPublicKey,
407 fido_parsing_utils::Materialize(
408 test_data::kTestGetAssertionCredentialId),
409 {FidoTransportProtocol::kBluetoothLowEnergy}},
410 {CredentialType::kPublicKey,
411 fido_parsing_utils::Materialize(kBogusCredentialId)},
412 });
413
Jun Choife176682018-08-30 07:49:14414 EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
Balazs Engedy159452d2018-08-16 15:18:18415 auto request_handler =
416 CreateGetAssertionHandlerWithRequest(std::move(request));
417 ExpectAllTransportsAreAllowedForRequest(request_handler.get());
418}
419
420TEST_F(FidoGetAssertionHandlerTest,
421 AllowedTransportsAreUnionOfTransportsLists) {
Balazs Engedy5b4891f2018-08-29 23:08:00422 auto request = CreateTestRequestWithCableExtension();
Balazs Engedy159452d2018-08-16 15:18:18423 request.SetAllowList({
424 {CredentialType::kPublicKey,
425 fido_parsing_utils::Materialize(
426 test_data::kTestGetAssertionCredentialId),
427 {FidoTransportProtocol::kBluetoothLowEnergy}},
428 {CredentialType::kPublicKey,
429 fido_parsing_utils::Materialize(kBogusCredentialId),
430 {FidoTransportProtocol::kInternal,
431 FidoTransportProtocol::kNearFieldCommunication}},
432 });
433
Jun Choife176682018-08-30 07:49:14434 EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
Balazs Engedy159452d2018-08-16 15:18:18435 auto request_handler =
436 CreateGetAssertionHandlerWithRequest(std::move(request));
437 ExpectAllowedTransportsForRequestAre(
438 request_handler.get(), {FidoTransportProtocol::kBluetoothLowEnergy,
439 FidoTransportProtocol::kInternal,
440 FidoTransportProtocol::kNearFieldCommunication});
441}
442
Balazs Engedy5b4891f2018-08-29 23:08:00443TEST_F(FidoGetAssertionHandlerTest,
444 CableDisabledIfAllowCredentialsListUndefinedButCableExtensionMissing) {
445 CtapGetAssertionRequest request(test_data::kRelyingPartyId,
Martin Kreichgauer90c625742018-10-31 04:24:15446 test_data::kClientDataJson);
Balazs Engedy5b4891f2018-08-29 23:08:00447 ASSERT_FALSE(!!request.cable_extension());
Jun Choife176682018-08-30 07:49:14448 EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
Balazs Engedy5b4891f2018-08-29 23:08:00449 auto request_handler =
450 CreateGetAssertionHandlerWithRequest(std::move(request));
451 ExpectAllowedTransportsForRequestAre(
452 request_handler.get(), {FidoTransportProtocol::kBluetoothLowEnergy,
453 FidoTransportProtocol::kUsbHumanInterfaceDevice,
454 FidoTransportProtocol::kNearFieldCommunication,
455 FidoTransportProtocol::kInternal});
456}
457
458TEST_F(FidoGetAssertionHandlerTest,
459 CableDisabledIfExplicitlyAllowedButCableExtensionMissing) {
460 CtapGetAssertionRequest request(test_data::kRelyingPartyId,
Martin Kreichgauer90c625742018-10-31 04:24:15461 test_data::kClientDataJson);
Balazs Engedy5b4891f2018-08-29 23:08:00462 ASSERT_FALSE(!!request.cable_extension());
463 request.SetAllowList({
464 {CredentialType::kPublicKey,
465 fido_parsing_utils::Materialize(
466 test_data::kTestGetAssertionCredentialId),
467 {FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
468 FidoTransportProtocol::kUsbHumanInterfaceDevice}},
469 });
470
471 auto request_handler =
472 CreateGetAssertionHandlerWithRequest(std::move(request));
473 ExpectAllowedTransportsForRequestAre(
474 request_handler.get(), {FidoTransportProtocol::kUsbHumanInterfaceDevice});
475}
476
Balazs Engedy159452d2018-08-16 15:18:18477TEST_F(FidoGetAssertionHandlerTest, SupportedTransportsAreOnlyBleAndNfc) {
478 const base::flat_set<FidoTransportProtocol> kBleAndNfc = {
479 FidoTransportProtocol::kBluetoothLowEnergy,
480 FidoTransportProtocol::kNearFieldCommunication,
481 };
482
483 set_supported_transports(kBleAndNfc);
Jun Choife176682018-08-30 07:49:14484 EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
Balazs Engedy5b4891f2018-08-29 23:08:00485 auto request_handler = CreateGetAssertionHandlerWithRequest(
486 CreateTestRequestWithCableExtension());
Balazs Engedy159452d2018-08-16 15:18:18487 ExpectAllowedTransportsForRequestAre(request_handler.get(), kBleAndNfc);
488}
489
Balazs Engedy5b4891f2018-08-29 23:08:00490TEST_F(FidoGetAssertionHandlerTest,
491 SupportedTransportsAreOnlyCableAndInternal) {
492 const base::flat_set<FidoTransportProtocol> kCableAndInternal = {
Balazs Engedy159452d2018-08-16 15:18:18493 FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
494 FidoTransportProtocol::kInternal,
495 };
496
Jun Choife176682018-08-30 07:49:14497 EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
Balazs Engedy5b4891f2018-08-29 23:08:00498 set_supported_transports(kCableAndInternal);
499 auto request_handler = CreateGetAssertionHandlerWithRequest(
500 CreateTestRequestWithCableExtension());
501 ExpectAllowedTransportsForRequestAre(request_handler.get(),
502 kCableAndInternal);
Balazs Engedy159452d2018-08-16 15:18:18503}
504
505TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyUsbTransportAllowed) {
Balazs Engedy5b4891f2018-08-29 23:08:00506 auto request = CreateTestRequestWithCableExtension();
Balazs Engedy159452d2018-08-16 15:18:18507 request.SetAllowList({
508 {CredentialType::kPublicKey,
509 fido_parsing_utils::Materialize(
510 test_data::kTestGetAssertionCredentialId),
511 {FidoTransportProtocol::kUsbHumanInterfaceDevice}},
512 });
513
514 set_supported_transports({FidoTransportProtocol::kUsbHumanInterfaceDevice});
515
516 auto request_handler =
517 CreateGetAssertionHandlerWithRequest(std::move(request));
518
519 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
520 device->ExpectCtap2CommandAndRespondWith(
521 CtapRequestCommand::kAuthenticatorGetAssertion,
522 test_data::kTestGetAssertionResponse);
523 discovery()->WaitForCallToStartAndSimulateSuccess();
524 discovery()->AddDevice(std::move(device));
525
526 get_assertion_callback().WaitForCallback();
527
528 EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
529 EXPECT_TRUE(get_assertion_callback().value<0>());
530 EXPECT_TRUE(request_handler->is_complete());
531 EXPECT_THAT(
532 request_handler->transport_availability_info().available_transports,
533 ::testing::UnorderedElementsAre(
534 FidoTransportProtocol::kUsbHumanInterfaceDevice));
535}
536
537TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyBleTransportAllowed) {
Balazs Engedy5b4891f2018-08-29 23:08:00538 auto request = CreateTestRequestWithCableExtension();
Balazs Engedy159452d2018-08-16 15:18:18539 request.SetAllowList({
540 {CredentialType::kPublicKey,
541 fido_parsing_utils::Materialize(
542 test_data::kTestGetAssertionCredentialId),
543 {FidoTransportProtocol::kBluetoothLowEnergy}},
544 });
545
546 set_supported_transports({FidoTransportProtocol::kBluetoothLowEnergy});
Jun Choife176682018-08-30 07:49:14547 EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
Balazs Engedy159452d2018-08-16 15:18:18548 auto request_handler =
549 CreateGetAssertionHandlerWithRequest(std::move(request));
550
551 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
552 device->SetDeviceTransport(FidoTransportProtocol::kBluetoothLowEnergy);
553 device->ExpectCtap2CommandAndRespondWith(
554 CtapRequestCommand::kAuthenticatorGetAssertion,
555 test_data::kTestGetAssertionResponse);
556 ble_discovery()->WaitForCallToStartAndSimulateSuccess();
557 ble_discovery()->AddDevice(std::move(device));
558
559 get_assertion_callback().WaitForCallback();
560
561 EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
562 EXPECT_TRUE(get_assertion_callback().value<0>());
563 EXPECT_TRUE(request_handler->is_complete());
564 EXPECT_THAT(
565 request_handler->transport_availability_info().available_transports,
566 ::testing::UnorderedElementsAre(
567 FidoTransportProtocol::kBluetoothLowEnergy));
568}
569
570TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyNfcTransportAllowed) {
Balazs Engedy5b4891f2018-08-29 23:08:00571 auto request = CreateTestRequestWithCableExtension();
Balazs Engedy159452d2018-08-16 15:18:18572 request.SetAllowList({
573 {CredentialType::kPublicKey,
574 fido_parsing_utils::Materialize(
575 test_data::kTestGetAssertionCredentialId),
576 {FidoTransportProtocol::kNearFieldCommunication}},
577 });
578
579 set_supported_transports({FidoTransportProtocol::kNearFieldCommunication});
580
581 auto request_handler =
582 CreateGetAssertionHandlerWithRequest(std::move(request));
583
584 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
585 device->SetDeviceTransport(FidoTransportProtocol::kNearFieldCommunication);
586 device->ExpectCtap2CommandAndRespondWith(
587 CtapRequestCommand::kAuthenticatorGetAssertion,
588 test_data::kTestGetAssertionResponse);
589 nfc_discovery()->WaitForCallToStartAndSimulateSuccess();
590 nfc_discovery()->AddDevice(std::move(device));
591
592 get_assertion_callback().WaitForCallback();
593
594 EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
595 EXPECT_TRUE(get_assertion_callback().value<0>());
596 EXPECT_TRUE(request_handler->is_complete());
597 EXPECT_THAT(
598 request_handler->transport_availability_info().available_transports,
599 ::testing::UnorderedElementsAre(
600 FidoTransportProtocol::kNearFieldCommunication));
601}
602
603TEST_F(FidoGetAssertionHandlerTest, SuccessWithOnlyInternalTransportAllowed) {
Balazs Engedy5b4891f2018-08-29 23:08:00604 auto request = CreateTestRequestWithCableExtension();
Balazs Engedy159452d2018-08-16 15:18:18605 request.SetAllowList({
606 {CredentialType::kPublicKey,
607 fido_parsing_utils::Materialize(
608 test_data::kTestGetAssertionCredentialId),
609 {FidoTransportProtocol::kInternal}},
610 });
611
612 set_supported_transports({FidoTransportProtocol::kInternal});
613
614 auto device = MockFidoDevice::MakeCtap(
615 ReadCTAPGetInfoResponse(test_data::kTestGetInfoResponsePlatformDevice));
616 EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
617 device->SetDeviceTransport(FidoTransportProtocol::kInternal);
618 device->ExpectCtap2CommandAndRespondWith(
Jun Choi6065c1d2018-08-23 19:04:48619 CtapRequestCommand::kAuthenticatorGetInfo,
620 test_data::kTestGetInfoResponsePlatformDevice);
621 device->ExpectCtap2CommandAndRespondWith(
Balazs Engedy159452d2018-08-16 15:18:18622 CtapRequestCommand::kAuthenticatorGetAssertion,
623 test_data::kTestGetAssertionResponse);
624 set_mock_platform_device(std::move(device));
625
626 auto request_handler =
627 CreateGetAssertionHandlerWithRequest(std::move(request));
628 get_assertion_callback().WaitForCallback();
629
630 EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
631 EXPECT_TRUE(get_assertion_callback().value<0>());
632 EXPECT_TRUE(request_handler->is_complete());
633 EXPECT_THAT(
634 request_handler->transport_availability_info().available_transports,
635 ::testing::UnorderedElementsAre(FidoTransportProtocol::kInternal));
636}
637
Jun Choie4aee4ff32018-08-13 19:35:07638// Tests a scenario where authenticator of incorrect transport type was used to
639// conduct CTAP GetAssertion call.
Balazs Engedy159452d2018-08-16 15:18:18640//
641// TODO(engedy): This should not happen, instead |allowCredentials| should be
642// filtered to only contain items compatible with the transport actually used to
643// talk to the authenticator.
Jun Choie4aee4ff32018-08-13 19:35:07644TEST_F(FidoGetAssertionHandlerTest, IncorrectTransportType) {
645 // GetAssertion request that expects GetAssertion call for credential
646 // |CredentialType::kPublicKey| to be signed with Cable authenticator.
Balazs Engedy5b4891f2018-08-29 23:08:00647 auto request = CreateTestRequestWithCableExtension();
Balazs Engedy159452d2018-08-16 15:18:18648 request.SetAllowList({
649 {CredentialType::kPublicKey,
650 fido_parsing_utils::Materialize(
651 test_data::kTestGetAssertionCredentialId),
652 {FidoTransportProtocol::kBluetoothLowEnergy}},
653 {CredentialType::kPublicKey,
654 fido_parsing_utils::Materialize(kBogusCredentialId),
655 {FidoTransportProtocol::kUsbHumanInterfaceDevice}},
656 });
Jun Choie4aee4ff32018-08-13 19:35:07657 auto request_handler =
658 CreateGetAssertionHandlerWithRequest(std::move(request));
659 discovery()->WaitForCallToStartAndSimulateSuccess();
660 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
661 // Since transport type of |device| is different from what the relying party
662 // defined in |request| above, this request should fail.
663 device->SetDeviceTransport(FidoTransportProtocol::kUsbHumanInterfaceDevice);
664 device->ExpectCtap2CommandAndRespondWith(
665 CtapRequestCommand::kAuthenticatorGetAssertion,
666 test_data::kTestGetAssertionResponse);
667
668 discovery()->AddDevice(std::move(device));
669
670 scoped_task_environment_.FastForwardUntilNoTasksRemain();
671 EXPECT_FALSE(get_assertion_callback().was_called());
672}
673
Martin Kreichgauer5bac1652018-08-22 16:41:10674// If a device with transport type kInternal returns a
675// CTAP2_ERR_OPERATION_DENIED error, the request should complete with
676// FidoReturnCode::kUserConsentDenied. Pending authenticators should be
677// cancelled.
678TEST_F(FidoGetAssertionHandlerTest,
679 TestRequestWithOperationDeniedErrorPlatform) {
Jun Choi6065c1d2018-08-23 19:04:48680 auto platform_device = MockFidoDevice::MakeCtapWithGetInfoExpectation(
681 test_data::kTestGetInfoResponsePlatformDevice);
Martin Kreichgauer5bac1652018-08-22 16:41:10682 platform_device->SetDeviceTransport(FidoTransportProtocol::kInternal);
683 platform_device->ExpectCtap2CommandAndRespondWithError(
684 CtapRequestCommand::kAuthenticatorGetAssertion,
685 CtapDeviceResponseCode::kCtap2ErrOperationDenied,
686 base::TimeDelta::FromMicroseconds(10));
Martin Kreichgauer5bac1652018-08-22 16:41:10687 set_mock_platform_device(std::move(platform_device));
688
689 auto other_device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
690 other_device->ExpectCtap2CommandAndDoNotRespond(
691 CtapRequestCommand::kAuthenticatorGetAssertion);
692 EXPECT_CALL(*other_device, Cancel);
693
694 auto request_handler = CreateGetAssertionHandlerCtap();
695 discovery()->WaitForCallToStartAndSimulateSuccess();
696 discovery()->AddDevice(std::move(other_device));
697
698 scoped_task_environment_.FastForwardUntilNoTasksRemain();
699 EXPECT_TRUE(get_assertion_callback().was_called());
700 EXPECT_EQ(FidoReturnCode::kUserConsentDenied,
701 get_assertion_callback().status());
702}
703
704// Like |TestRequestWithOperationDeniedErrorPlatform|, but with a
Martin Kreichgauer8e6f1b32018-08-24 13:42:49705// cross-platform device.
Martin Kreichgauer5bac1652018-08-22 16:41:10706TEST_F(FidoGetAssertionHandlerTest,
707 TestRequestWithOperationDeniedErrorCrossPlatform) {
708 auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
709 device->ExpectCtap2CommandAndRespondWithError(
710 CtapRequestCommand::kAuthenticatorGetAssertion,
711 CtapDeviceResponseCode::kCtap2ErrOperationDenied);
712
713 auto request_handler = CreateGetAssertionHandlerCtap();
714 discovery()->WaitForCallToStartAndSimulateSuccess();
715 discovery()->AddDevice(std::move(device));
716
717 scoped_task_environment_.FastForwardUntilNoTasksRemain();
Martin Kreichgauer8e6f1b32018-08-24 13:42:49718 EXPECT_TRUE(get_assertion_callback().was_called());
719 EXPECT_EQ(FidoReturnCode::kUserConsentDenied,
720 get_assertion_callback().status());
Martin Kreichgauer5bac1652018-08-22 16:41:10721}
722
Martin Kreichgauer75377812018-11-09 18:58:13723#if defined(OS_WIN)
Martin Kreichgauerdf06312d2018-11-08 00:43:36724class GetAssertionRequestHandlerWinTest : public ::testing::Test {
725 protected:
726 base::test::ScopedTaskEnvironment scoped_task_environment_;
727 ScopedFakeWinWebAuthnApi scoped_fake_win_webauthn_api_;
728};
729
730// Verify that the request handler instantiates a HID device backed
731// FidoDeviceAuthenticator or a WinNativeCrossPlatformAuthenticator, depending
732// on feature flag and API availability.
733TEST_F(GetAssertionRequestHandlerWinTest, TestWinUsbDiscovery) {
734 enum class DeviceType {
735 kHid,
736 kWinNative,
737 };
738 const struct TestCase {
739 bool enable_win_webauthn_api;
740 bool enable_feature_flag;
741 DeviceType expect_device_type;
742 } test_cases[] = {
743 {false, false, DeviceType::kHid},
744 {false, true, DeviceType::kHid},
745 {true, false, DeviceType::kHid},
746 {true, true, DeviceType::kWinNative},
747 };
748 size_t i = 0;
749 for (const auto& test : test_cases) {
750 SCOPED_TRACE(i++);
751 scoped_fake_win_webauthn_api_.set_available(test.enable_win_webauthn_api);
752 base::test::ScopedFeatureList scoped_feature_list;
753 // Feature is default off (even with API present).
754 if (test.enable_feature_flag)
755 scoped_feature_list.InitAndEnableFeature(kWebAuthUseNativeWinApi);
756
Martin Kreichgauerb129ae52018-11-14 21:26:33757 // Simulate a connected HID device.
758 ScopedFakeHidManager fake_hid_manager;
759 fake_hid_manager.AddFidoHidDevice("guid");
760
Martin Kreichgauerdf06312d2018-11-08 00:43:36761 TestGetAssertionRequestCallback cb;
Martin Kreichgauerdf06312d2018-11-08 00:43:36762 auto handler = std::make_unique<GetAssertionRequestHandler>(
Martin Kreichgauerb129ae52018-11-14 21:26:33763 fake_hid_manager.service_manager_connector(),
Martin Kreichgauerdf06312d2018-11-08 00:43:36764 base::flat_set<FidoTransportProtocol>(
765 {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
766 CtapGetAssertionRequest(test_data::kRelyingPartyId,
767 test_data::kClientDataJson),
768
769 cb.callback());
770 scoped_task_environment_.RunUntilIdle();
771
Martin Kreichgauerdf06312d2018-11-08 00:43:36772 EXPECT_EQ(1u, handler->AuthenticatorsForTesting().size());
773 // Crudely distinguish authenticator type by FidoAuthenticator::GetId.
774 EXPECT_EQ(test.expect_device_type == DeviceType::kHid
775 ? "hid:guid"
Martin Kreichgauerb129ae52018-11-14 21:26:33776 : WinWebAuthnApiAuthenticator::kAuthenticatorId,
Martin Kreichgauerdf06312d2018-11-08 00:43:36777 handler->AuthenticatorsForTesting().begin()->second->GetId());
778 }
779}
Martin Kreichgauer75377812018-11-09 18:58:13780#endif // defined(OS_WIN)
Martin Kreichgauerdf06312d2018-11-08 00:43:36781
Jun Choi4fc8b7812018-04-05 07:39:07782} // namespace device