def test_parse_bytes(self): info = Info(_INFO) self.assertEqual(info.versions, ['U2F_V2', 'FIDO_2_0']) self.assertEqual(info.extensions, ['uvm', 'hmac-secret']) self.assertEqual(info.aaguid, _AAGUID) self.assertEqual(info.options, { 'rk': True, 'up': True, 'plat': False, 'clientPin': False }) self.assertEqual(info.max_msg_size, 1200) self.assertEqual(info.pin_protocols, [1]) self.assertEqual( info.data, { Info.KEY.VERSIONS: ['U2F_V2', 'FIDO_2_0'], Info.KEY.EXTENSIONS: ['uvm', 'hmac-secret'], Info.KEY.AAGUID: _AAGUID, Info.KEY.OPTIONS: { 'clientPin': False, 'plat': False, 'rk': True, 'up': True }, Info.KEY.MAX_MSG_SIZE: 1200, Info.KEY.PIN_PROTOCOLS: [1] })
def test_make_credential_ctap2(self): dev = mock.Mock() dev.capabilities = CAPABILITY.CBOR client = Fido2Client(dev, APP_ID) client.ctap = mock.MagicMock() client.ctap.get_info.return_value = Info(_INFO_NO_PIN) client.ctap.make_credential.return_value = AttestationObject(_MC_RESP) attestation, client_data = client.make_credential(rp, user, challenge, timeout=1) self.assertIsInstance(attestation, AttestationObject) self.assertIsInstance(client_data, ClientData) client.ctap.get_info.assert_called_with() client.ctap.make_credential.assert_called_with( client_data.hash, rp, user, [{ 'type': 'public-key', 'alg': -7 }], None, None, None, None, None, 1, None) self.assertEqual(client_data.get('origin'), APP_ID) self.assertEqual(client_data.get('type'), 'webauthn.create') self.assertEqual(client_data.get('challenge'), challenge)
def test_parse_bytes(self): info = Info(_INFO) self.assertEqual(info.versions, ["U2F_V2", "FIDO_2_0"]) self.assertEqual(info.extensions, ["uvm", "hmac-secret"]) self.assertEqual(info.aaguid, _AAGUID) self.assertEqual(info.options, { "rk": True, "up": True, "plat": False, "clientPin": False }) self.assertEqual(info.max_msg_size, 1200) self.assertEqual(info.pin_uv_protocols, [1]) self.assertEqual( info.data, { Info.KEY.VERSIONS: ["U2F_V2", "FIDO_2_0"], Info.KEY.EXTENSIONS: ["uvm", "hmac-secret"], Info.KEY.AAGUID: _AAGUID, Info.KEY.OPTIONS: { "clientPin": False, "plat": False, "rk": True, "up": True, }, Info.KEY.MAX_MSG_SIZE: 1200, Info.KEY.PIN_UV_PROTOCOLS: [1], }, )
def test_parse_bytes(self): info = Info.from_dict(cbor.decode(_INFO)) self.assertEqual(info.versions, ["U2F_V2", "FIDO_2_0"]) self.assertEqual(info.extensions, ["uvm", "hmac-secret"]) self.assertEqual(info.aaguid, _AAGUID) self.assertEqual(info.options, { "rk": True, "up": True, "plat": False, "clientPin": False }) self.assertEqual(info.max_msg_size, 1200) self.assertEqual(info.pin_uv_protocols, [1]) assert info[0x01] == ["U2F_V2", "FIDO_2_0"] assert info[0x02] == ["uvm", "hmac-secret"] assert info[0x03] == _AAGUID assert info[0x04] == { "clientPin": False, "plat": False, "rk": True, "up": True, } assert info[0x05] == 1200 assert info[0x06] == [1]
def test_make_credential_existing_key(self, PatchedCTAP2): dev = mock.Mock() dev.capabilities = CAPABILITY.CBOR ctap2 = mock.MagicMock() ctap2.get_info.return_value = Info(_INFO_NO_PIN) ctap2.make_credential.side_effect = CtapError( CtapError.ERR.CREDENTIAL_EXCLUDED) PatchedCTAP2.return_value = ctap2 client = Fido2Client(dev, APP_ID) try: client.make_credential( PublicKeyCredentialCreationOptions( rp, user, challenge, [{ "type": "public-key", "alg": -7 }], authenticator_selection={ "userVerification": "discouraged" }, )) self.fail("make_credential did not raise error") except ClientError as e: self.assertEqual(e.code, ClientError.ERR.DEVICE_INELIGIBLE) ctap2.get_info.assert_called_with() ctap2.make_credential.assert_called_once()
def test_make_credential_ctap2(self, PatchedCtap2): dev = mock.Mock() dev.capabilities = CAPABILITY.CBOR ctap2 = mock.MagicMock() ctap2.get_info.return_value = Info.from_dict(cbor.decode(_INFO_NO_PIN)) ctap2.info = ctap2.get_info() ctap2.make_credential.return_value = AttestationResponse.from_dict( cbor.decode(_MC_RESP)) PatchedCtap2.return_value = ctap2 client = Fido2Client(dev, APP_ID) response = client.make_credential( PublicKeyCredentialCreationOptions( rp, user, challenge, [{ "type": "public-key", "alg": -7 }], timeout=1000, authenticator_selection={"userVerification": "discouraged"}, )) self.assertIsInstance(response.attestation_object, AttestationObject) self.assertIsInstance(response.client_data, CollectedClientData) ctap2.make_credential.assert_called_with( response.client_data.hash, rp, user, [{ "type": "public-key", "alg": -7 }], None, None, None, None, None, event=mock.ANY, on_keepalive=mock.ANY, ) self.assertEqual(response.client_data.origin, APP_ID) self.assertEqual(response.client_data.type, "webauthn.create") self.assertEqual(response.client_data.challenge, challenge)
def test_make_credential_existing_key(self): dev = mock.Mock() dev.capabilities = CAPABILITY.CBOR client = Fido2Client(dev, APP_ID) client.ctap = mock.MagicMock() client.ctap.get_info.return_value = Info(_INFO_NO_PIN) client.ctap.make_credential.side_effect = CtapError( CtapError.ERR.CREDENTIAL_EXCLUDED) try: client.make_credential(rp, user, challenge, timeout=1) self.fail('make_credential did not raise error') except ClientError as e: self.assertEqual(e.code, ClientError.ERR.DEVICE_INELIGIBLE) client.ctap.get_info.assert_called_with() client.ctap.make_credential.assert_called_once()
def test_make_credential_ctap2(self, PatchedCTAP2): dev = mock.Mock() dev.capabilities = CAPABILITY.CBOR ctap2 = mock.MagicMock() ctap2.get_info.return_value = Info(_INFO_NO_PIN) ctap2.make_credential.return_value = AttestationObject(_MC_RESP) PatchedCTAP2.return_value = ctap2 client = Fido2Client(dev, APP_ID) attestation, client_data = client.make_credential( PublicKeyCredentialCreationOptions( rp, user, challenge, [{ "type": "public-key", "alg": -7 }], timeout=1000, authenticator_selection={"userVerification": "discouraged"}, )) self.assertIsInstance(attestation, AttestationObject) self.assertIsInstance(client_data, ClientData) ctap2.get_info.assert_called_with() ctap2.make_credential.assert_called_with( client_data.hash, rp, user, [{ "type": "public-key", "alg": -7 }], None, None, None, None, None, mock.ANY, None, ) self.assertEqual(client_data.get("origin"), APP_ID) self.assertEqual(client_data.get("type"), "webauthn.create") self.assertEqual(client_data.challenge, challenge)
def test_make_credential_wrong_app_id(self, PatchedCTAP2): dev = mock.Mock() dev.capabilities = CAPABILITY.CBOR ctap2 = mock.MagicMock() ctap2.get_info.return_value = Info(_INFO_NO_PIN) PatchedCTAP2.return_value = ctap2 client = Fido2Client(dev, APP_ID) try: client.make_credential( { 'id': 'bar.example.com', 'name': 'Invalid RP' }, user, challenge, timeout=1) self.fail('make_credential did not raise error') except ClientError as e: self.assertEqual(e.code, ClientError.ERR.BAD_REQUEST)
def test_make_credential_wrong_app_id(self, PatchedCTAP2): dev = mock.Mock() dev.capabilities = CAPABILITY.CBOR ctap2 = mock.MagicMock() ctap2.get_info.return_value = Info(_INFO_NO_PIN) PatchedCTAP2.return_value = ctap2 client = Fido2Client(dev, APP_ID) try: client.make_credential( PublicKeyCredentialCreationOptions( {"id": "bar.example.com", "name": "Invalid RP"}, user, challenge, [{"type": "public-key", "alg": -7}], ) ) self.fail("make_credential did not raise error") except ClientError as e: self.assertEqual(e.code, ClientError.ERR.BAD_REQUEST)
def test_info_with_extra_field(self): info = Info(_INFO_EXTRA_KEY) self.assertEqual(info.versions, ['U2F_V2', 'FIDO_2_0']) self.assertEqual(info.data[7], 8)
def test_info_with_extra_field(self): info = Info.from_dict(cbor.decode(_INFO_EXTRA_KEY)) self.assertEqual(info.versions, ["U2F_V2", "FIDO_2_0"])
try: auth_resp = _call_polling( self.ctap1_poll_delay, event, on_keepalive, self.ctap1.authenticate, client_param, app_param, cred["id"], ) return [ AssertionResponse.from_ctap1(app_param, cred, auth_resp) ] except ClientError as e: if e.code == ClientError.ERR.TIMEOUT: raise # Other errors are ignored so we move to the next. raise ClientError.ERR.DEVICE_INELIGIBLE() _WIN_INFO = Info.create(["U2F_V2", "FIDO_2_0"]) if platform.system().lower() == "windows": try: from .win_api import ( WinAPI, WebAuthNAuthenticatorAttachment, WebAuthNUserVerificationRequirement, WebAuthNAttestationConvoyancePreference, ) except Exception: # nosec # TODO: Make this less generic pass