def test_create_not_supported_attestation(): """test for internal class check""" device = SoftWebauthnDevice() pkcco = copy.deepcopy(PKCCO) pkcco['publicKey']['attestation'] = 'direct' with pytest.raises(ValueError): device.create(pkcco, 'https://example.org')
def test_create_not_supported_type(): """test for internal class check""" device = SoftWebauthnDevice() pkcco = copy.deepcopy(PKCCO) pkcco['publicKey']['pubKeyCredParams'][0]['alg'] = -8 with pytest.raises(ValueError): device.create(pkcco, 'https://example.org')
def test_profile_webauthn_register_route(live_server, sl_user): # pylint: disable=unused-argument """register new credential for user""" device = SoftWebauthnDevice() sl_user.get(url_for('auth.profile_webauthn_register_route', _external=True)) # some javascript code must be emulated webdriver_waituntil(sl_user, js_variable_ready('window.pkcco_raw')) pkcco = cbor.decode( b64decode( sl_user.execute_script('return window.pkcco_raw;').encode( 'utf-8'))) attestation = device.create(pkcco, 'https://%s' % webauthn.rp.id) sl_user.execute_script( 'pack_attestation(CBOR.decode(Sner.base64_to_array_buffer("%s")));' % b64encode(cbor.encode(attestation)).decode('utf-8')) # and back to standard test codeflow sl_user.find_element_by_xpath( '//form[@id="webauthn_register_form"]//input[@name="name"]').send_keys( 'pytest token') sl_user.find_element_by_xpath( '//form[@id="webauthn_register_form"]//input[@type="submit"]').click() user = User.query.filter(User.username == 'pytest_user').one() assert user.webauthn_credentials
def test_webauthn_register_route(cl_user): """register new credential for user""" device = SoftWebauthnDevice() response = cl_user.get(url_for('app.webauthn_register_route')) # some javascript code must be emulated pkcco = cbor.decode( b64decode( cl_user.post(url_for('app.webauthn_pkcco_route'), { 'csrf_token': get_csrf_token(cl_user) }).body)) attestation = device.create(pkcco, 'https://%s' % webauthn.rp.ident) attestation_data = { 'clientDataJSON': attestation['response']['clientDataJSON'], 'attestationObject': attestation['response']['attestationObject'] } form = response.form form['attestation'] = b64encode(cbor.encode(attestation_data)) # and back to standard test codeflow form['name'] = 'pytest token' response = form.submit() assert response.status_code == HTTPStatus.FOUND user = User.query.filter(User.username == 'pytest_user').one() assert user.webauthn_credentials
def test_webauthn_register_new_key(test_client, init_database): sign_in_response = sign_in(test_client, "dave", "wselfknskjdksdaiujlj") device = SoftWebauthnDevice() begin_register_response = test_client.post("/webauthn/register/begin", data=json.dumps( {"resident": False})) pkcco = cbor.decode(begin_register_response.data) attestation = device.create(pkcco, f"https://{TestConfig.RP_ID}") attestation_data = cbor.encode({ "clientDataJSON": attestation["response"]["clientDataJSON"], "attestationObject": attestation["response"]["attestationObject"], }) raw_response = test_client.post( "/webauthn/register/complete", input_stream=BytesIO(attestation_data), content_type="application/cbor", ) registration_response = cbor.decode(raw_response.data) assert registration_response == {"status": "OK"} user = User.query.filter_by(username="******").first() webauthn = Webauthn.query.filter_by(user_id=user.did).first() assert webauthn assert webauthn.number == 1 assert webauthn.is_enabled is False
def test_create(): """test create""" device = SoftWebauthnDevice() attestation = device.create(PKCCO, 'https://example.org') assert attestation assert device.private_key assert device.rp_id == 'example.org'
def test_register(): """test registering generated credential""" device = SoftWebauthnDevice() server = Fido2Server( PublicKeyCredentialRpEntity('example.org', 'test server')) exclude_credentials = [] options, state = server.register_begin( { 'id': b'randomhandle', 'name': 'username', 'displayName': 'User Name' }, exclude_credentials) attestation = device.create(options, 'https://example.org') auth_data = server.register_complete( state, ClientData(attestation['response']['clientDataJSON']), AttestationObject(attestation['response']['attestationObject'])) assert isinstance(auth_data, AuthenticatorData)
def test_example_server_registration(client): # pylint: disable=redefined-outer-name """Registration example""" # User holds an authenticator. # # NOTE: SoftWebauthnDevice emulates mixed client and authenticator behavior # and can be used for testing Webauthn/FIDO2 enabled applications during # continuous integration test-cases. device = SoftWebauthnDevice() # The browser starts registration process by requesting # publicKeyCredentialCreationOptions (pkcco) from the server/web # application/relying party (RP). # # NOTE: The transfer encoding and format is not in scope of Webauthn spec, # Yubico fido2 example server uses application/cbor. pkcco = cbor.decode(client.post('/api/register/begin').data) print('publicKeyCredentialCreationOptions: ', pkcco) # publicKeyCredentialCreationOptions object is passed from browser/client # to the authenticator. Authenticator will generate new credential and # return credential object (attestation). attestation = device.create(pkcco, 'https://localhost') print('new credential attestation: ', attestation) # Browser conveys the attestation data to the RP for registration. attestation_data = cbor.encode({ 'clientDataJSON': attestation['response']['clientDataJSON'], 'attestationObject': attestation['response']['attestationObject'] }) raw_response = client.post( '/api/register/complete', input_stream=BytesIO(attestation_data), content_type='application/cbor' ) registration_response = cbor.decode(raw_response.data) print('registration response:', registration_response) # After verification, RP stores attested credential data associated with # user account for later authentication. assert registration_response == {'status': 'OK'}
def init_database(): db.create_all() user1 = User(username="******", email="*****@*****.**") user1.set_password("[email protected]<") user2 = User(username="******", email="*****@*****.**") user2.set_password("m7ZTbjQdwuUFU/Zy6la+k6uUtniBExIgEhmBPduKexM=") user3 = User(username="******", email="*****@*****.**") user3.set_password("wselfknskjdksdaiujlj") db.session.add(user1) db.session.add(user2) db.session.add(user3) user4 = User(username="******", email="*****@*****.**") user4.set_password("c1c149afbf4c8996fb92427ae41e4649b934ca") user5 = User(username="******", email="*****@*****.**") user5.set_password("9df1c362e4df3e51edd1acde9") user6 = User(username="******", email="*****@*****.**") user6.set_password("ukehjwqbjhwqkbejw") user7 = User(username="******", email="*****@*****.**") user7.set_password("qghjoiwjiklwek") user8 = User(username="******", email="*****@*****.**") user8.set_password("2398wqshjduiwd8932") db.session.add(user4) db.session.add(user5) db.session.add(user6) db.session.add(user7) db.session.add(user8) db.session.commit() got_user4 = User.query.filter_by(username="******").first() webauthn_for_user4 = Webauthn( number=0, is_enabled=True, user_id=got_user4.did ) got_user5 = User.query.filter_by(username="******").first() webauthn_for_user5 = Webauthn( number=1, is_enabled=True, user_identifier=b"\x7e" + os.urandom(31), user_id=got_user5.did, ) device = SoftWebauthnDevice() pkcco = cbor.decode( cbor.encode( { "publicKey": { "rp": {"id": TestConfig.RP_ID, "name": "Demo server"}, "user": { "id": webauthn_for_user5.user_identifier, "icon": "https://example.com/image.png", "name": got_user5.username, "displayName": f"Tests - {got_user5.username}", }, "timeout": 30000, "challenge": ( b"\xcc\x8e\x03\x04\xdb6bd\xa0d\x98\xa9Vz0p.x" b"\xa4\xf5\xd4\xf6%\xf8\x86zt\x1d\ny\xf9<" ), "pubKeyCredParams": [ {"alg": -7, "type": "public-key"}, {"alg": -8, "type": "public-key"}, {"alg": -37, "type": "public-key"}, {"alg": -257, "type": "public-key"}, ], "excludeCredentials": [], "authenticatorSelection": { "userVerification": "discouraged", "authenticatorAttachment": "cross-platform", }, } } ) ) attestation = device.create(pkcco, f"https://{TestConfig.RP_ID}") KeyList.priv_one = device.private_key att_obj = AttestationObject(attestation["response"]["attestationObject"]) client_data = ClientData(attestation["response"]["clientDataJSON"]) auth_data = att_obj.auth_data key_for_user5 = Key( name="Key 1", aaguid=auth_data.credential_data.aaguid, credential_id=auth_data.credential_data.credential_id, client_data_hash=hashlib.sha256(client_data).digest(), public_key=cbor.encode(auth_data.credential_data.public_key), counter=att_obj.auth_data.counter, attestation=attestation["response"]["attestationObject"], info="TODO", last_access=datetime.utcnow(), created=datetime.utcnow(), user_id=got_user5.did, ) db.session.add(webauthn_for_user4) db.session.add(webauthn_for_user5) db.session.add(key_for_user5) # Users for activating Webauthn got_user6 = User.query.filter_by(username="******").first() webauthn_for_user6 = Webauthn( number=2, is_enabled=False, user_id=got_user6.did ) got_user7 = User.query.filter_by(username="******").first() webauthn_for_user7 = Webauthn( number=1, is_enabled=False, user_id=got_user7.did ) db.session.add(webauthn_for_user6) db.session.add(webauthn_for_user7) got_user8 = User.query.filter_by(username="******").first() webauthn_for_user8 = Webauthn( number=1, is_enabled=False, user_id=got_user8.did ) first_key_for_user8 = Key( name="Key 1", aaguid=b"", credential_id=b"againnotrealbutrequiredtolistkeyproperly", client_data_hash=hashlib.sha256(b"a").digest(), public_key=b"", counter=0, attestation=b"", info="TODO", last_access=datetime.utcnow(), created=datetime.utcnow(), user_id=got_user8.did, ) second_key_for_user8 = Key( name="Key 2", aaguid=b"", credential_id=b"notrealbutnecessarytodelete", client_data_hash=hashlib.sha256(b"a").digest(), public_key=b"", counter=0, attestation=b"", info="TODO", last_access=datetime.utcnow(), created=datetime.utcnow(), user_id=got_user8.did, ) db.session.add(webauthn_for_user8) db.session.add(first_key_for_user8) db.session.add(second_key_for_user8) db.session.commit() yield db db.drop_all()