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 fido2_login_complete(req): user = None logreq('fido2_login_complete', req) username = req.session.get(FIDO2_USER_KEY, None) if username: user = get_user_model().objects.get(username=username) if user: creds = get_fido2_credentials(user) data = cbor.decode(req.body) crid = data['credentialId'] cdat = ClientData(data['clientDataJSON']) adat = AuthenticatorData(data['authenticatorData']) csig = data['signature'] stat = get_fido2_state(req) try: SERVER.authenticate_complete(stat, creds, crid, cdat, adat, csig) except ValueError as e: logger.warn('Failed fido2 authentication', e) return HttpResponseForbidden() found = False for a in user.authenticators.all(): if a.crid == crid: a.inc_counter() found = True break if not found: logger.warn( f'Failed to bump fido2 counter for cred-id "{crid}" owned by "{user.username}".' ) auth.login(req, user) messages.info( req, f'Welcome back {user.get_full_name() or user.username}.') logger.info(f'login_complete successful for user "{user.username}".') return get_cbor_resp(redirect='/') return HttpResponseForbidden()
def complete_reg(request): try: data = cbor.decode(request.body) client_data = ClientData(data['clientDataJSON']) att_obj = AttestationObject((data['attestationObject'])) server = get_server() auth_data = server.register_complete(request.session['fido_state'], client_data, att_obj) encoded = websafe_encode(auth_data.credential_data) key = UserKey.objects.create( user=request.user, properties={ "device": encoded, "type": att_obj.fmt, "domain": request.get_host(), }, key_type=KEY_TYPE_FIDO2, ) write_session(request, key) messages.success(request, 'FIDO2 Token added!') return JsonResponse({'status': 'OK'}) except Exception: logger.exception("Error completing FIDO2 registration.") return JsonResponse({ 'status': 'ERR', "message": "Error on server, please try again later", })
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 fido2_keys_user_validate(user_id): keys = list_fido2_keys(user_id) credentials = list(map(lambda k: pickle.loads(base64.b64decode(k.key)), keys)) data = request.get_json() cbor_data = cbor.decode(base64.b64decode(data["payload"])) credential_id = cbor_data['credentialId'] client_data = ClientData(cbor_data['clientDataJSON']) auth_data = AuthenticatorData(cbor_data['authenticatorData']) signature = cbor_data['signature'] Config.FIDO2_SERVER.authenticate_complete( get_fido2_session(user_id), credentials, credential_id, client_data, auth_data, signature ) user_to_verify = get_user_by_id(user_id=user_id) user_to_verify.current_session_id = str(uuid.uuid4()) user_to_verify.logged_in_at = datetime.utcnow() user_to_verify.failed_login_count = 0 save_model_user(user_to_verify) return jsonify({'status': 'OK'})
def test_ES256_parse_verify(self): key = CoseKey.parse(cbor.decode(_ES256_KEY)) self.assertIsInstance(key, ES256) self.assertEqual( key, { 1: 2, 3: -7, -1: 1, -2: a2b_hex( b'A5FD5CE1B1C458C530A54FA61B31BF6B04BE8B97AFDE54DD8CBB69275A8A1BE1' ), # noqa -3: a2b_hex( b'FA3A3231DD9DEED9D1897BE5A6228C59501E4BCD12975D3DFF730F01278EA61C' ) # noqa }) key.verify( a2b_hex( b'0021F5FC0B85CD22E60623BCD7D1CA48948909249B4776EB515154E57B66AE12010000002C' + # noqa b'7B89F12A9088B0F5EE0EF8F6718BCCC374249C31AEEBAEB79BD0450132CD536C' ), # noqa a2b_hex( b'304402202B3933FE954A2D29DE691901EB732535393D4859AAA80D58B08741598109516D0220236FBE6B52326C0A6B1CFDC6BF0A35BDA92A6C2E41E40C3A1643428D820941E0' ) # noqa )
def page(self) -> CBORPageResult: assert user.id is not None if not is_two_factor_login_enabled(user.id): raise MKGeneralException( _("Two-factor authentication not enabled")) data: dict[str, object] = cbor.decode(request.get_data()) credential_id = data["credentialId"] client_data = ClientData(data["clientDataJSON"]) auth_data = AuthenticatorData(data["authenticatorData"]) signature = data["signature"] logger.debug("ClientData: %r", client_data) logger.debug("AuthenticatorData: %r", auth_data) make_fido2_server().authenticate_complete( session.session_info.webauthn_action_state, [ AttestedCredentialData.unpack_from(v["credential_data"])[0] for v in load_two_factor_credentials(user.id) ["webauthn_credentials"].values() ], credential_id, client_data, auth_data, signature, ) session.session_info.webauthn_action_state = None set_two_factor_completed() return {"status": "OK"}
def test_login_webauthn(live_server, selenium, webauthn_credential_factory): # pylint: disable=unused-argument """test login by webauthn""" device = SoftWebauthnDevice() device.cred_init(webauthn.rp.id, b'randomhandle') wncred = webauthn_credential_factory.create(initialized_device=device) # factory post_generate does not call commit to propagate self.attr changes, that messes the actual db state when # accessing from different process such as real browser db.session.commit() selenium.get(url_for('auth.login_route', _external=True)) selenium.find_element_by_xpath( '//form//input[@name="username"]').send_keys(wncred.user.username) selenium.find_element_by_xpath('//form//input[@type="submit"]').click() # some javascript code must be emulated webdriver_waituntil(selenium, js_variable_ready('window.pkcro_raw')) pkcro = cbor.decode( b64decode( selenium.execute_script('return window.pkcro_raw;').encode( 'utf-8'))) assertion = device.get(pkcro, 'https://%s' % webauthn.rp.id) selenium.execute_script( 'authenticate_assertion(CBOR.decode(Sner.base64_to_array_buffer("%s")));' % b64encode(cbor.encode(assertion)).decode('utf-8')) # and back to standard test codeflow webdriver_waituntil( selenium, EC.presence_of_element_located((By.XPATH, '//a[text()="Logout"]')))
def test_login_webauthn(client, webauthn_credential_factory): """test login by webauthn""" device = SoftWebauthnDevice() device.cred_init(webauthn.rp.id, b'randomhandle') wncred = webauthn_credential_factory.create(initialized_device=device) form = client.get(url_for('auth.login_route')).form form['username'] = wncred.user.username response = form.submit() assert response.status_code == HTTPStatus.FOUND response = response.follow() # some javascript code muset be emulated pkcro = cbor.decode( b64decode( client.post(url_for('auth.login_webauthn_pkcro_route'), { 'csrf_token': get_csrf_token(client) }).body)) assertion = device.get(pkcro, f'https://{webauthn.rp.id}') assertion_data = { 'credentialRawId': assertion['rawId'], 'authenticatorData': assertion['response']['authenticatorData'], 'clientDataJSON': assertion['response']['clientDataJSON'], 'signature': assertion['response']['signature'], 'userHandle': assertion['response']['userHandle'] } form = response.form form['assertion'] = b64encode(cbor.encode(assertion_data)) response = form.submit() # and back to standard test codeflow assert response.status_code == HTTPStatus.FOUND response = client.get(url_for('index_route')) assert response.lxml.xpath('//a[text()="Logout"]')
def bench_recovery_makecredential(iterations=100, repeats=10, num_seeds=1): iterations = int(iterations) clientDataJSON_hash = os.urandom(32) primary_authnr = Authenticator() backup_authnr = Authenticator() basic_make_credential(primary_authnr, clientDataJSON_hash) allowList = [{ 'type': 'public-key', 'id': i } for i in primary_authnr._credentials.keys()] for i in range(num_seeds - 1): primary_authnr.import_recovery_seed( Authenticator().export_recovery_seed([0])) primary_authnr.import_recovery_seed(backup_authnr.export_recovery_seed([0 ])) recovery_allowCredentials = [{ 'id': ctap2.AttestedCredentialData(cred).credential_id, 'type': 'public-key' } for cred in ctap2.AuthenticatorData( cbor.decode( generate_backups_get_assertion(primary_authnr, clientDataJSON_hash, allowList)) [2]).extensions['recovery']['creds']] return iterations, repeats, timeit.repeat( stmt=lambda: recovery_make_credential( backup_authnr, clientDataJSON_hash, recovery_allowCredentials), number=iterations, repeat=repeats, )
def complete_reg(request): try: data = cbor.decode(request.body) client_data = ClientData(data['clientDataJSON']) att_obj = AttestationObject((data['attestationObject'])) server = get_server() auth_data = server.register_complete(request.session['fido_state'], client_data, att_obj) encoded = websafe_encode(auth_data.credential_data) UserKey.objects.create( username=request.user.get_username(), properties={ "device": encoded, "type": att_obj.fmt }, key_type="FIDO2", ) return JsonResponse({'status': 'OK'}) except: return JsonResponse({ 'status': 'ERR', "message": "Error on server, please try again later", })
def authenticate_complete(request): credentials = [] username = request.session.get("base_username", request.user.get_username()) server = get_server() credentials = get_user_credentials(username) data = cbor.decode(request.body) credential_id = data['credentialId'] client_data = ClientData(data['clientDataJSON']) auth_data = AuthenticatorData(data['authenticatorData']) signature = data['signature'] cred = server.authenticate_complete(request.session.pop('fido_state'), credentials, credential_id, client_data, auth_data, signature) for k in UserKey.objects.filter(username=username, key_type="FIDO2", enabled=1): if AttestedCredentialData(websafe_decode( k.properties["device"])).credential_id == cred.credential_id: k.last_used = timezone.now() k.save() mfa = {"verified": True, "method": "FIDO2", 'id': k.id} if getattr(settings, "MFA_RECHECK", False): mfa["next_check"] = next_check() request.session["mfa"] = mfa res = login(request) return JsonResponse({'status': "OK", "redirect": res["location"]}) return JsonResponse({'status': "err"})
def get_assertion(authenticator, request_json): request = json.loads(request_json) pkcro = request['publicKeyCredentialRequestOptions'] collectedClientData = { 'type': 'webauthn.get', 'challenge': pkcro['challenge'], 'origin': 'https://localhost:8443', } clientDataJSON = json.dumps(collectedClientData, indent=None).encode('utf-8') clientDataJSON_hash = sha256(clientDataJSON) authenticator_response = cbor.decode(authenticator.authenticator_get_assertion(cbor.encode({ 0x01: pkcro['rpId'], 0x02: clientDataJSON_hash, 0x03: [{'id': base64.urlsafe_b64decode(c['id']), 'type': 'public-key'} for c in pkcro['allowCredentials']], 0x04: pkcro['extensions'], }))) authenticatorData = authenticator_response[0x02] sig = authenticator_response[0x03] credential = { 'type': 'public-key', 'id': base64.urlsafe_b64encode(authenticator_response[0x01]['id']).decode('utf-8'), 'response': { 'authenticatorData': base64.urlsafe_b64encode(authenticatorData).decode('utf-8'), 'clientDataJSON': base64.urlsafe_b64encode(clientDataJSON).decode('utf-8'), 'signature': base64.urlsafe_b64encode(sig).decode('utf-8'), }, 'clientExtensionResults': {}, } print(json.dumps(credential, indent=2))
def ctap2_to_webauthn_attestation_object(attObj_cbor): attObj = cbor.decode(attObj_cbor) return cbor.encode({ 'fmt': attObj[0x01], 'authData': attObj[0x02], 'attStmt': attObj[0x03], })
def _call( self, cmd: int, data: bytes = b"", event: Event = None, on_keepalive: FunctionType = None, ): if cmd != hid.CTAPHID.CBOR: raise CtapError(CtapError.ERR.INVALID_COMMAND) if not data: raise CtapError(CtapError.ERR.INVALID_PARAMETER) ctap2_cmd = ctap2.Ctap2.CMD.from_bytes(data[:1], 'big') handler = self._ctap2_cmd_to_handler.get(ctap2_cmd) if not handler: raise CtapError(CtapError.ERR.INVALID_COMMAND) if len(data) == 1: return handler() # noinspection PyBroadException try: ctap2_req: dict = cbor.decode(data[1:]) except Exception: raise CtapError(CtapError.ERR.INVALID_CBOR) if not isinstance(ctap2_req, dict): raise CtapError(CtapError.ERR.INVALID_CBOR) # noinspection PyArgumentList return handler(ctap2_req)
def profile_webauthn_register_route(): """register credential for current user""" user = User.query.get(current_user.id) form = WebauthnRegisterForm() if form.validate_on_submit(): try: attestation = cbor.decode(b64decode(form.attestation.data)) auth_data = webauthn.register_complete( session.pop('webauthn_register_state'), ClientData(attestation['clientDataJSON']), AttestationObject(attestation['attestationObject'])) db.session.add(WebauthnCredential( user_id=user.id, user_handle=session.pop('webauthn_register_user_handle'), credential_data=cbor.encode(auth_data.credential_data.__dict__), name=form.name.data)) db.session.commit() return redirect(url_for('auth.profile_route')) except (KeyError, ValueError) as e: current_app.logger.exception(e) flash('Error during registration.', 'error') return render_template('auth/profile/webauthn_register.html', form=form)
def test_login_webauthn(live_server, selenium, test_user): # pylint: disable=unused-argument """test login by webauthn""" device = SoftWebauthnDevice() device.cred_init(webauthn.rp.id, b'randomhandle') persist_and_detach( WebauthnCredential(user=test_user, user_handle=device.user_handle, credential_data=cbor.encode( device.cred_as_attested().__dict__))) selenium.get(url_for('auth.login_route', _external=True)) selenium.find_element_by_xpath( '//form//input[@name="username"]').send_keys(test_user.username) selenium.find_element_by_xpath('//form//input[@type="submit"]').click() # some javascript code must be emulated webdriver_waituntil(selenium, js_variable_ready('window.pkcro_raw')) pkcro = cbor.decode( b64decode( selenium.execute_script('return window.pkcro_raw;').encode( 'utf-8'))) assertion = device.get(pkcro, 'https://%s' % webauthn.rp.id) selenium.execute_script( 'authenticate_assertion(CBOR.decode(Sner.base64_to_array_buffer("%s")));' % b64encode(cbor.encode(assertion)).decode('utf-8')) # and back to standard test codeflow webdriver_waituntil( selenium, EC.presence_of_element_located((By.XPATH, '//a[text()="Logout"]')))
def _add_token_to_user(self, registration_data, state): data = registration_data + (b'=' * (len(registration_data) % 4)) data = base64.urlsafe_b64decode(data) data = cbor.decode(data) client_data = ClientData(data['clientDataJSON']) attestation = data['attestationObject'] att_obj = AttestationObject(attestation) server = get_webauthn_server(self.app.config.fido2_rp_id) auth_data = server.register_complete(state, client_data, att_obj) cred_data = auth_data.credential_data cred_id = cred_data.credential_id credential = Webauthn.from_dict( dict( keyhandle=cred_id.hex(), credential_data=base64.urlsafe_b64encode(cred_data).decode( 'ascii'), app_id=self.app.config.fido2_rp_id, attest_obj=base64.b64encode(attestation).decode('ascii'), description='ctap1 token', created_by='test_security', )) self.test_user.credentials.add(credential) self.app.central_userdb.save(self.test_user, check_sync=False) return credential
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 page(self) -> CBORPageResult: assert user.id is not None user.need_permission("general.manage_2fa") raw_data = request.get_data() logger.debug("Raw request: %r", raw_data) data: dict[str, object] = cbor.decode(raw_data) client_data = ClientData(data["clientDataJSON"]) att_obj = AttestationObject(data["attestationObject"]) logger.debug("Client data: %r", client_data) logger.debug("Attestation object: %r", att_obj) auth_data = make_fido2_server().register_complete( session.session_info.webauthn_action_state, client_data, att_obj ) ident = auth_data.credential_data.credential_id.hex() credentials = load_two_factor_credentials(user.id, lock=True) if ident in credentials["webauthn_credentials"]: raise MKGeneralException(_("Your WebAuthn credetial is already in use")) credentials["webauthn_credentials"][ident] = WebAuthnCredential( { "credential_id": ident, "registered_at": int(time.time()), "alias": "", "credential_data": bytes(auth_data.credential_data), } ) save_two_factor_credentials(user.id, credentials) flash(_("Registration successful")) return {"status": "OK"}
def test_EdDSA_parse_verify(self): key = CoseKey.parse(cbor.decode(_EdDSA_KEY)) self.assertIsInstance(key, EdDSA) self.assertEqual( key, { 1: 1, 3: -8, -1: 6, -2: a2b_hex( 'EE9B21803405D3CF45601E58B6F4C06EA93862DE87D3AF903C5870A5016E86F5' ) # noqa }) key.verify( a2b_hex( b'a379a6f6eeafb9a55e378c118034e2751e682fab9f2d30ab13d2125586ce1947010000000500a11a323057d1103784ddff99a354ddd42348c2f00e88d8977b916cabf92268' ), # noqa a2b_hex( b'e8c927ef1a57c738ff4ba8d6f90e06d837a5219eee47991f96b126b0685d512520c9c2eedebe4b88ff2de2b19cb5f8686efc7c4261e9ed1cb3ac5de50869be0a' ) # noqa )
def complete_reg(request): """Completes the registeration, called by API""" try: data = cbor.decode(request.body) client_data = ClientData(data['clientDataJSON']) att_obj = AttestationObject((data['attestationObject'])) server = getServer() auth_data = server.register_complete(request.session['fido_state'], client_data, att_obj) encoded = websafe_encode(auth_data.credential_data) uk = User_Keys() uk.username = request.user.username uk.properties = { "device": encoded, "type": att_obj.fmt, } uk.owned_by_enterprise = getattr(settings, "MFA_OWNED_BY_ENTERPRISE", False) uk.key_type = "FIDO2" uk.save() return HttpResponse(simplejson.dumps({'status': 'OK'})) except Exception as exp: try: from raven.contrib.django.raven_compat.models import client client.captureException() except: pass return HttpResponse( simplejson.dumps({ 'status': 'ERR', "message": "Error on server, please try again later" }))
def test_RS256_parse_verify(self): key = CoseKey.parse(cbor.decode(_RS256_KEY)) self.assertIsInstance(key, RS256) self.assertEqual( key, { 1: 3, 3: -257, -1: a2b_hex( b'B610DCE84B65029FAE24F7BF8A1730D37BC91435642A628E691E9B030BF3F7CEC59FF91CBE82C54DE16C136FA4FA8A58939B5A950B32E03073592FEC8D8B33601C04F70E5E2D5CF7B4E805E1990EA5A86928A1B390EB9026527933ACC03E6E41DC0BE40AA5EB7B9B460743E4DD80895A758FB3F3F794E5E9B8310D3A60C28F2410D95CF6E732749A243A30475267628B456DE770BC2185BBED1D451ECB0062A3D132C0E4D842E0DDF93A444A3EE33A85C2E913156361713155F1F1DC64E8E68ED176466553BBDE669EB82810B104CB4407D32AE6316C3BD6F382EC3AE2C5FD49304986D64D92ED11C25B6C5CF1287233545A987E9A3E169F99790603DBA5C8AD' ), # noqa -2: a2b_hex(b'010001') # noqa }) key.verify( a2b_hex( b'0021F5FC0B85CD22E60623BCD7D1CA48948909249B4776EB515154E57B66AE12010000002E' + # noqa b'CC9340FD84950987BA667DBE9B2C97C7241E15E2B54869A0DD1CE2013C4064B8' ), # noqa a2b_hex( b'071B707D11F0E7F62861DFACA89C4E674321AD8A6E329FDD40C7D6971348FBB0514E7B2B0EFE215BAAC0365C4124A808F8180D6575B710E7C01DAE8F052D0C5A2CE82F487C656E7AD824F3D699BE389ADDDE2CBF39E87A8955E93202BAE8830AB4139A7688DFDAD849F1BB689F3852BA05BED70897553CC44704F6941FD1467AD6A46B4DAB503716D386FE7B398E78E0A5A8C4040539D2C9BFA37E4D94F96091FFD1D194DE2CA58E9124A39757F013801421E09BD261ADA31992A8B0386A80AF51A87BD0CEE8FDAB0D4651477670D4C7B245489BED30A57B83964DB79418D5A4F5F2E5ABCA274426C9F90B007A962AE15DFF7343AF9E110746E2DB9226D785C6' ) # noqa )
def login_webauthn_route(): """login webauthn route""" user = User.query.filter( User.id == session.get('webauthn_login_user_id')).one_or_none() if not user: return login_manager.unauthorized() form = WebauthnLoginForm() if form.validate_on_submit(): try: assertion = cbor.decode(b64decode(form.assertion.data)) webauthn.authenticate_complete( session.pop('webauthn_login_state'), webauthn_credentials(user), assertion['credentialRawId'], ClientData(assertion['clientDataJSON']), AuthenticatorData(assertion['authenticatorData']), assertion['signature']) regenerate_session() login_user(user) return redirect_after_login() except (KeyError, ValueError) as e: current_app.logger.exception(e) flash('Login error during Webauthn authentication.', 'error') return render_template('auth/login_webauthn.html', form=form)
def assertion_response(): app.logger.debug("/assertion/response") data = cbor.decode(request.get_data()) app.logger.debug('post_data:\n%s', pp.pformat(data)) credential_id = data['id'] raw_id = data['rawId'] client_data = ClientData(data['clientDataJSON']) app.logger.debug('client_data:\n%s', pp.pformat(client_data)) auth_data = AuthenticatorData(data['authenticatorData']) app.logger.debug('auth_data:\n%s', pp.pformat(auth_data)) signature = data['signature'] credential = Credential.get(credential_id) if not credential: abort(404) credential_data = credential.to_credential_data() server.authenticate_complete(session.pop('state'), [credential_data], raw_id, client_data, auth_data, signature) # Checking signCount if auth_data.counter > credential.counter: # TODO: flask_ldapconn is not allow to store integer value credential.counter = str(auth_data.counter) credential.save() else: app.logger.warn('wrong counter: stored counter=%d but %d asserted', credential.counter, auth_data.counter) abort(404) user = credential.user if not user: abort(404) login_user(user) return cbor.encode({'status': 'OK'})
def authenticate_complete(request): data = cbor.decode(request.body) credential_id = data["credentialId"] client_data = ClientData(data["clientDataJSON"]) auth_data = AuthenticatorData(data["authenticatorData"]) signature = data["signature"] credentials = [ row.credential for row in User.objects.get( pk=request.session['user']).fidocredential_set.all() ] fido_server.authenticate_complete( request.session.pop("state"), credentials, credential_id, client_data, auth_data, signature, ) try: user = User.objects.get(pk=request.session.pop('user')) except User.DoesNotExist: raise Http404 else: # If we're here, we've already confirmed the user has the # username and the password. login(request, user) return HttpResponse( cbor.encode({"status": "OK"}), content_type='application/cbor', )
def authenticate_complete(request): server = get_server() data = cbor.decode(request.body) credential_id = data['credentialId'] client_data = ClientData(data['clientDataJSON']) auth_data = AuthenticatorData(data['authenticatorData']) signature = data['signature'] cred = server.authenticate_complete(request.session.pop('fido_state'), get_user_credentials(request), credential_id, client_data, auth_data, signature) keys = UserKey.objects.filter( user=request.user, key_type=KEY_TYPE_FIDO2, enabled=True, ) for key in keys: if AttestedCredentialData(websafe_decode( key.properties["device"])).credential_id == cred.credential_id: write_session(request, key) res = login(request) return JsonResponse({'status': "OK", "redirect": res["location"]}) return JsonResponse({'status': "err"})
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 complete_reg(request): try: data = cbor.decode(request.body) client_data = ClientData(data['clientDataJSON']) att_obj = AttestationObject((data['attestationObject'])) server = getServer() auth_data = server.register_complete(request.session['fido_state'], client_data, att_obj) encoded = websafe_encode(auth_data.credential_data) uk = User_Keys() uk.username = request.user.username uk.properties = { "device": encoded, "type": att_obj.fmt, } uk.key_type = "FIDO2" uk.save() return HttpResponse(simplejson.dumps({'status': 'OK'})) except Exception as exp: from raven.contrib.django.raven_compat.models import client import traceback client.captureException() return HttpResponse( simplejson.dumps({ 'status': 'ERR', "message": "Error on server, please try again later" }))
def authenticate_complete(): if not User.query.count(): abort(404) try: data = cbor.decode(request.get_data()) credential_id = data["credentialId"] client_data = ClientData(data["clientDataJSON"]) auth_data = AuthenticatorData(data["authenticatorData"]) signature = data["signature"] except IndexError: abort(400) user = User.get_by(credential_id) if user is None: abort(401) server.authenticate_complete( session.pop("state"), [user.create_data], credential_id, client_data, auth_data, signature, ) return cbor.encode({"status": "OK"})