def webauthn_finish_login(): user = User() cookie = None challenge = session.get('challenge') password = session.get('login_password') assertion_response = request.form credential_id = assertion_response.get('id') db, person = auth.getPersonByCredentialID(credential_id) if not person: return make_response(jsonify({'fail': 'User does not exist.'}), 401) webauthn_user = webauthn.WebAuthnUser( person.ukey, person.username, person.display_name, person.icon_url, person.credential_id, person.pub_key, person.sign_count, person.rp_id) webauthn_assertion_response = webauthn.WebAuthnAssertionResponse( webauthn_user, assertion_response, challenge, ORIGIN, uv_required=False) # User Verification try: sign_count = webauthn_assertion_response.verify() except Exception as e: return make_response(jsonify({'fail': 'Assertion failed. Error: {}'.format(e)}), 401) # Update counter. person.sign_count = sign_count db.commit() # TODO: Is this check not performing anything useful? if not person.username: return make_response(jsonify({'fail': 'You must supply a username to log in.'}), 401) elif not password: return make_response(jsonify({'fail': 'You must supply a password to log in.'}), 401) else: cookie = user.checkLogin(person.username, password) if not cookie: return make_response(jsonify({'fail': 'Invalid username or password.'}), 401) nexturl = request.values.get('nexturl', https_url_for('index')) response = make_response(jsonify({'nexturl': nexturl}), 200) ## Be careful not to include semicolons in cookie value; see ## https://github.com/mitsuhiko/werkzeug/issues/226 for more ## details. response.set_cookie('PyZoobarLogin', cookie) return response
def webauthn_finish_transfer(): cookie = None challenge = session.get('challenge') amount = session.get('transfer_amount') recipient = session.get('transfer_recipient') clientExtensions = session.get('clientExtensions') assertion_response = request.form credential_id = assertion_response.get('id') # Make sure action is performed on correct user if g.user.person.credential_id != credential_id: return make_response( jsonify({ 'fail': 'Credential ID does not match that of logged in user.' }), 401) db, person = auth.getPersonByCredentialID(credential_id) if not person: return make_response(jsonify({'fail': 'User does not exist.'}), 401) webauthn_user = webauthn.WebAuthnUser(person.ukey, person.username, person.display_name, person.icon_url, person.credential_id, person.pub_key, person.sign_count, person.rp_id) def verify_authenticator_extensions_fn(client_data, expected_authenticator_extensions): client_data_extensions = client_data.get('clientExtensions') # Make sure that the extensions dicts have the same keys if client_data_extensions.keys( ) != expected_authenticator_extensions.keys(): return False # Make sure that the key is only `txAuthSimple` for now if client_data_extensions.keys() != {'txAuthSimple'}: return False # Test the `txAuthSimple` extension, except for line breaks if client_data_extensions['txAuthSimple'].replace('\n', '') != \ expected_authenticator_extensions['txAuthSimple'].replace('\n', ''): return False # All passed return True webauthn_assertion_response = webauthn.WebAuthnAssertionResponse( webauthn_user, assertion_response, challenge, ORIGIN, uv_required=False, # User Verification expected_assertion_authenticator_extensions=clientExtensions, verify_authenticator_extensions_fn=verify_authenticator_extensions_fn, ) try: sign_count = webauthn_assertion_response.verify() except Exception as e: return make_response( jsonify({'fail': 'Assertion failed. Error: {}'.format(e)}), 401) # Update counter. person.sign_count = sign_count db.commit() # Perform the zoobar transfer bank.transfer(g.user.person.username, recipient, amount) nexturl = request.values.get('nexturl', https_url_for('transfer_page')) response = make_response(jsonify({'nexturl': nexturl}), 200) return response
def loginhelper(*args, **kwargs): if not logged_in(): return redirect(https_url_for('login_page') + "?nexturl=" + request.url.replace("http://localhost", "https://localhost:8080")) else: return page(*args, **kwargs)
def logout(): if logged_in(): g.user.logout() response = redirect(https_url_for('login_page')) response.set_cookie('PyZoobarLogin', '') return response
def login_page(): nexturl = request.values.get('nexturl', https_url_for('index')) return render_template('login.html', nexturl=nexturl, login_username=Markup(request.form.get('login_username', '')))
def webauthn_finish_register(): user = User() cookie = None challenge = session['challenge'] username = session['register_username'] display_name = session['register_display_name'] password = session['register_password'] ukey = session['register_ukey'] registration_response = request.form trust_anchor_dir = os.path.join( os.path.dirname(os.path.abspath(__file__)), TRUST_ANCHOR_DIR) trusted_attestation_cert_required = False self_attestation_permitted = True none_attestation_permitted = True webauthn_registration_response = webauthn.WebAuthnRegistrationResponse( RP_ID, ORIGIN, registration_response, challenge, trust_anchor_dir, trusted_attestation_cert_required, self_attestation_permitted, none_attestation_permitted, uv_required=False) # User Verification try: webauthn_credential = webauthn_registration_response.verify() except Exception as e: return make_response( jsonify({'fail': 'Registration failed. Error: {}'.format(e)}), 401) # Step 17. # # Check that the credentialId is not yet registered to any other user. # If registration is requested for a credential that is already registered # to a different user, the Relying Party SHOULD fail this registration # ceremony, or it MAY decide to accept the registration, e.g. while deleting # the older registration. if auth.credentialIDExists(webauthn_credential.credential_id): return make_response( jsonify({'fail': 'Credential ID already exists.'}), 401) if sys.version_info >= (3, 0): webauthn_credential.credential_id = str( webauthn_credential.credential_id, "utf-8") webauthn_credential.public_key = str( webauthn_credential.public_key, "utf-8") cookie = user.addRegistration(ukey=ukey, username=username, password=password, display_name=display_name, pub_key=webauthn_credential.public_key, credential_id=webauthn_credential.credential_id, sign_count=webauthn_credential.sign_count, rp_id=RP_ID, icon_url='https://localhost:8080') if not cookie: return make_response(jsonify({'fail': 'User already exists.'}), 401) nexturl = request.values.get('nexturl', https_url_for('index')) response = make_response(jsonify({'nexturl': nexturl}), 200) ## Be careful not to include semicolons in cookie value; see ## https://github.com/mitsuhiko/werkzeug/issues/226 for more ## details. response.set_cookie('PyZoobarLogin', cookie) return response