diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..347cf2a9073124b259908bfa7bb8f851ce0af5ef --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +# Versions from Debian Buster +ldap3==2.4.1 +flask==1.0.2 +Flask-SQLAlchemy==2.1 +qrcode==6.1 +fido2==0.5.0 +Flask-OAuthlib==0.9.5 diff --git a/uffd/mfa/views.py b/uffd/mfa/views.py index 2237db2d6f3ab03ca504f34797cd81c8f68354f7..408e6a982e1d65edf09735b98b58ca7753e9d742 100644 --- a/uffd/mfa/views.py +++ b/uffd/mfa/views.py @@ -1,9 +1,8 @@ from flask import Blueprint, render_template, session, request, redirect, url_for, flash, current_app import urllib.parse -from fido2.webauthn import PublicKeyCredentialRpEntity, UserVerificationRequirement from fido2.client import ClientData -from fido2.server import Fido2Server +from fido2.server import Fido2Server, RelyingParty from fido2.ctap2 import AttestationObject, AuthenticatorData from fido2 import cbor @@ -104,7 +103,7 @@ def delete_totp(id): return redirect(url_for('mfa.setup')) def get_webauthn_server(): - return Fido2Server(PublicKeyCredentialRpEntity(urllib.parse.urlsplit(request.url).hostname, "uffd")) + return Fido2Server(RelyingParty(urllib.parse.urlsplit(request.url).hostname, "uffd")) @bp.route('/setup/webauthn/begin', methods=['POST']) @login_required() @@ -123,11 +122,10 @@ def setup_webauthn_begin(): "displayName": user.displayname, }, creds, - user_verification=UserVerificationRequirement.DISCOURAGED, - authenticator_attachment="cross-platform", + user_verification='discouraged', ) session["webauthn-state"] = state - return cbor.encode(registration_data) + return cbor.dumps(registration_data) @bp.route('/setup/webauthn/complete', methods=['POST']) @login_required() @@ -135,7 +133,7 @@ def setup_webauthn_begin(): def setup_webauthn_complete(): user = get_current_user() server = get_webauthn_server() - data = cbor.decode(request.get_data()) + data = cbor.loads(request.get_data())[0] client_data = ClientData(data["clientDataJSON"]) att_obj = AttestationObject(data["attestationObject"]) auth_data = server.register_complete(session["webauthn-state"], client_data, att_obj) @@ -143,7 +141,7 @@ def setup_webauthn_complete(): db.session.add(method) db.session.commit() print("REGISTERED CREDENTIAL:", auth_data.credential_data) - return cbor.encode({"status": "OK"}) + return cbor.dumps({"status": "OK"}) @bp.route('/setup/webauthn/<int:id>/delete') @login_required() @@ -163,9 +161,9 @@ def auth_webauthn_begin(): creds = [method.cred_data.credential_data for method in methods] if not creds: abort(404) - auth_data, state = server.authenticate_begin(creds, user_verification=UserVerificationRequirement.DISCOURAGED) + auth_data, state = server.authenticate_begin(creds, user_verification='discouraged') session["webauthn-state"] = state - return cbor.encode(auth_data) + return cbor.dumps(auth_data) @bp.route("/auth/webauthn/complete", methods=["POST"]) def auth_webauthn_complete(): @@ -175,7 +173,7 @@ def auth_webauthn_complete(): creds = [method.cred_data.credential_data for method in methods] if not creds: abort(404) - data = cbor.decode(request.get_data()) + data = cbor.loads(request.get_data())[0] credential_id = data["credentialId"] client_data = ClientData(data["clientDataJSON"]) auth_data = AuthenticatorData(data["authenticatorData"]) @@ -189,7 +187,7 @@ def auth_webauthn_complete(): signature, ) session['user_mfa'] = True - return cbor.encode({"status": "OK"}) + return cbor.dumps({"status": "OK"}) @bp.route('/auth', methods=['GET']) @login_required(skip_mfa=True)