Beispiel #1
0
def webauthn_begin_assertion(election):
    email = request.form.get('email')

    if not len(email):
        return make_response(jsonify({'fail': 'Invalid email.'}), 401)

    user = Authority.query.filter(Election.name == election,
                                  Authority.email == email).first()
    if not user:
        return make_response(jsonify({'fail': 'User does not exist.'}), 401)
    if not user.webauthn:
        session['email'] = email
        return jsonify({'alt-login': '******'})
    if not user.credential_id:
        return make_response(jsonify({'fail': 'Unknown credential ID.'}), 401)

    if 'challenge' in session:
        del session['challenge']
    challenge = generate_challenge(32)
    session['challenge'] = challenge

    webauthn_user = webauthn.WebAuthnUser(user.ukey, user.email, user.name,
                                          user.icon_url, user.credential_id,
                                          user.pub_key, user.sign_count,
                                          user.rp_id)

    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(
        webauthn_user, challenge)

    return jsonify(webauthn_assertion_options.assertion_dict)
def login():
    challenge = session.get('challenge')
    credential_id = request.json.get('id')
    user_handle = request.json.get('userHandle')
    client_data = request.json.get('clientData')
    auth_data = request.json.get('authData')
    signature = request.json.get('signature')
    assertion_client_extensions = request.json.get('assertionClientExtensions')

    user = next((u for u in USERS.values() if u['credential_id'] == credential_id), None)
    if user is None:
        return jsonify(status='failure', error='User with given credential ID not found')

    user_id, username, credential_id, public_key = user['id'], user['username'], user['credential_id'], user['public_key']
    webauthn_user = webauthn.WebAuthnUser(user_id=user_id, username=username, display_name=username, icon_url=ICON_URL, credential_id=credential_id, public_key=public_key, sign_count=0, rp_id=RELYING_PARTY_ID)
    webauthn_assertion_response = webauthn.WebAuthnAssertionResponse(
        webauthn_user=webauthn_user,
        assertion_response={'id': credential_id, 'userHandle': user_handle, 'clientData': client_data, 'authData': auth_data, 'signature': signature, 'assertionClientExtensions': assertion_client_extensions},
        challenge=challenge,
        origin=ORIGIN,
    )
    try:
        webauthn_assertion_response.verify()
    except Exception as e:
        return jsonify(status='failure', error=str(e))

    return jsonify(status='success', user=user)
Beispiel #3
0
def login():
    challenge = session.get('challenge')
    credential_id = request.json.get('id')
    user_handle = request.json.get('userHandle')
    client_data = request.json.get('clientData')
    auth_data = request.json.get('authData')
    signature = request.json.get('signature')
    assertion_client_extensions = request.json.get('assertionClientExtensions')

    user = next((u for u in ADMIN_USERS.values() if u.credential_id == credential_id), None)
    if user is None:
        logger.info(f"Login start failed: no user with credential ID {credential_id}")
        return jsonify(status='failure', error='User with given credential_id not found')
    logger.info(f"Login submitted for user {user.username} with challenge {challenge}")

    webauthn_user = webauthn.WebAuthnUser(user_id=user.id, username=user.username, display_name=user.username, icon_url=ICON_URL, credential_id=user.credential_id, public_key=user.public_key, sign_count=0, rp_id=RELYING_PARTY_ID)
    webauthn_assertion_response = webauthn.WebAuthnAssertionResponse(
        webauthn_user=webauthn_user,
        assertion_response={'id': user.credential_id, 'userHandle': user_handle, 'clientData': client_data, 'authData': auth_data, 'signature': signature, 'assertionClientExtensions': assertion_client_extensions},
        challenge=challenge,
        origin=ORIGIN,
    )
    try:
        webauthn_assertion_response.verify()
    except Exception as e:
        logger.info(f"Login failed: {e}")
        return jsonify(status='failure', error=str(e))

    logger.info(f"Login completed for user {user.username}")
    login_user(user, remember=False)
    return jsonify(status='success')
Beispiel #4
0
def verify_assertion():
    challenge = session.get('challenge')
    assertion_response = request.form
    credential_id = assertion_response.get('id')

    user = User.query.filter_by(credential_id=credential_id).first()
    if not user:
        return make_response(jsonify({'fail': 'User does not exist.'}), 401)

    webauthn_user = webauthn.WebAuthnUser(user.ukey, user.username,
                                          user.display_name, user.icon_url,
                                          user.credential_id, user.pub_key,
                                          user.sign_count, user.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 jsonify({'fail': 'Assertion failed. Error: {}'.format(e)})

    # Update counter.
    user.sign_count = sign_count
    db.session.add(user)
    db.session.commit()

    login_user(user)

    return jsonify(
        {'success': 'Successfully authenticated as {}'.format(user.username)})
Beispiel #5
0
def webauthn_begin_assertion():
    username = request.form.get('login_username')

    if not util.validate_username(username):
        return make_response(jsonify({'fail': 'Invalid username.'}), 401)

    user = User.query.filter_by(username=username).first()

    if not user:
        return make_response(jsonify({'fail': 'User does not exist.'}), 401)
    if not user.credential_id:
        return make_response(jsonify({'fail': 'Unknown credential ID.'}), 401)

    if 'challenge' in session:
        del session['challenge']

    challenge = util.generate_challenge(32)

    session['challenge'] = challenge

    webauthn_user = webauthn.WebAuthnUser(user.ukey, user.username,
                                          user.display_name, user.icon_url,
                                          user.credential_id, user.pub_key,
                                          user.sign_count, user.rp_id)

    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(
        webauthn_user, challenge)

    return jsonify(webauthn_assertion_options.assertion_dict)
Beispiel #6
0
def webauthn_begin_assertion():
    jsonData = request.get_json()
    username = jsonData['username']

    if not util.validate_username(username):
        return make_response(jsonify({'fail': 'Invalid username.'}), 401)

    user = database.query_db("select * from Users where username=?",[username])[0]
    if len(user) == 0:
        return make_response(jsonify({'fail': 'User does not exist.'}), 401)
    if not user[4]:
        return make_response(jsonify({'fail': 'Unknown credential ID.'}), 401)


    challenge = util.generate_challenge(32)

    # We strip the padding from the challenge stored in the session
    # for the reasons outlined in the comment in webauthn_begin_activate.
    toStoreChallenge = challenge.rstrip('=')
    try:
        insert = database.insert_db("insert into PublicKeyCredentialCreationOptions VALUES (?,?,?,?,?,?)",[None, None,user[0],None,username,toStoreChallenge])
    except:
        update = database.insert_db("update PublicKeyCredentialCreationOptions SET challenge=? where user_username=?",[toStoreChallenge,username])
    webauthn_user = webauthn.WebAuthnUser(
        user[0], user[1], user[2], user[6],
        user[4], user[3], user[5], user[7])

    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(
        webauthn_user, challenge)

    return jsonify(webauthn_assertion_options.assertion_dict)
Beispiel #7
0
def verify_assertion(request):
    print("verify_assertion")
    challenge = request.session.get('challenge', False)
    assertion_response = request.POST
    credential_id = assertion_response.get('id')

    user = User.objects.filter(credential_id=credential_id).first()
    if not user:
        return JsonResponse({'fail': 'User does not exist.'})
    webauthn_user = webauthn.WebAuthnUser(
        user.ukey, user.username, user.display_name, user.icon_url,
        user.credential_id, user.pub_key, user.sign_count, user.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 JsonResponse({'fail': 'Assertion failed. Error: {}'.format(e)})
    # Update counter.
    user.sign_count = sign_count
    user.save()

    login(request, user)

    return JsonResponse({
        'success':
            'Successfully authenticated as {}'.format(user.username)
    })
Beispiel #8
0
def login_challenge():
    data = LoginChallengeSchema().load(request.get_json())
    email = data["email"]

    fake_user = User.generate_fake(email=email)
    user = User.query.filter_by(email=email).first() or fake_user

    challenge = random_string()
    webauthn_users = [
        webauthn.WebAuthnUser(
            user_id=authenticator.user.id,
            username=authenticator.user.email,
            display_name=authenticator.user.name,
            icon_url=app.config["WEBAUTHN_ICON_URL"],
            credential_id=authenticator.credential_id,
            public_key=authenticator.public_key,
            sign_count=authenticator.sign_count,
            rp_id=app.config["WEBAUTHN_RP_ID"],
        )
        for authenticator in user.authenticators
    ]

    options = webauthn.WebAuthnAssertionOptions(
        webauthn_users, challenge
    ).assertion_dict

    token = guard.encode_jwt_token(
        user, is_login=True, email=email, challenge=challenge
    )

    return {
        "token": token,
        "options": options,
    }
def webauthn_begin_login():
    username = request.form.get('login_username')
    password = request.form.get('login_password')

    if not util.validate_username(username):
        return make_response(jsonify({'fail': 'Invalid username.'}), 401)

    _, person = auth.getPerson(username)

    if not person:
        return make_response(jsonify({'fail': 'User does not exist.'}), 401)
    if not person.credential_id:
        return make_response(jsonify({'fail': 'Unknown credential ID.'}), 401)

    session.pop('challenge', None)
    session.pop('login_password', None)

    challenge = util.generate_challenge(32)

    # We strip the padding from the challenge stored in the session
    # for the reasons outlined in the comment in webauthn_begin_activate.
    session['challenge'] = challenge.rstrip('=')
    session['login_password'] = password
    
    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_options = webauthn.WebAuthnAssertionOptions(
        webauthn_user, challenge)
    
    return jsonify(webauthn_assertion_options.assertion_dict)
Beispiel #10
0
def webauthn_begin_assertion(request):
    challenge = util.generate_challenge(32)
    request.session["challenge"] = challenge

    user = util.get_user(request)

    username = user.get_username()
    display_name = user.get_full_name()

    keys = WebAuthnKey.objects.filter(user=user)

    webauthn_users = []
    for key in keys:
        webauthn_users.append(
            webauthn.WebAuthnUser(
                key.ukey,
                username,
                display_name,
                settings.WEBAUTHN_ICON_URL,
                key.credential_id,
                key.public_key,
                key.sign_count,
                settings.RELYING_PARTY_ID,
            ))

    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(
        webauthn_users, challenge)

    return JsonResponse(webauthn_assertion_options.assertion_dict)
Beispiel #11
0
def login():
    claims = current_custom_claims()
    if not claims.get("is_login", False):
        return "", 401

    data = LoginSchema().load(request.get_json())

    email = claims["email"]
    credential_id = data["id"]

    authenticator = Authenticator.query.filter(
        Authenticator.credential_id == credential_id,
        Authenticator.user.has(email=email),
    ).first()

    if not authenticator:
        return {"error": "authenticator not found"}, 401

    webauthn_user = webauthn.WebAuthnUser(
        user_id=authenticator.user.id,
        username=authenticator.user.email,
        display_name=authenticator.user.name,
        icon_url=app.config["WEBAUTHN_ICON_URL"],
        credential_id=authenticator.credential_id,
        public_key=authenticator.public_key,
        sign_count=authenticator.sign_count,
        rp_id=app.config["WEBAUTHN_RP_ID"],
    )

    response = webauthn.WebAuthnAssertionResponse(
        webauthn_user=webauthn_user,
        challenge=claims["challenge"],
        assertion_response=data,
        origin=app.config["WEBAUTHN_ORIGIN"],
    )

    try:
        sign_count = response.verify()
    except Exception as exc:
        return {"error": str(exc)}, 401

    authenticator.sign_count = sign_count
    authenticator.last_used_at = datetime.now(timezone.utc)
    db.session.add(authenticator)
    db.session.commit()

    return (
        {
            "token": guard.encode_jwt_token(authenticator.user),
            "user": UserSchema().dump(authenticator.user),
            "authenticator": AuthenticatorSchema().dump(authenticator),
        },
        200,
    )
Beispiel #12
0
 def webauthnuser(self):
     return webauthn.WebAuthnUser(
         self.ukey,
         self.user.email,
         str(self.user),
         settings.SITE_URL,
         self.credential_id,
         self.pub_key,
         self.sign_count,
         urlparse(settings.SITE_URL).netloc
     )
Beispiel #13
0
def verify_assertion():
    jsonData = request.get_json()
    AuthenticatorAttestationResponse = jsonData['AuthenticatorAttestationResponse']
    clientDataJSON = AuthenticatorAttestationResponse['clientDataJSON']
    clientDataJSON_padding = clientDataJSON.ljust((int)(math.ceil(len(clientDataJSON) / 4)) * 4, '=')
    clientDataJSON = base64.b64decode(clientDataJSON_padding).decode('utf8')
    clientDataJSONparsed = json.loads(clientDataJSON)
    retrievedChallenge = clientDataJSONparsed['challenge']
    try:
        data = database.query_db("select * from PublicKeyCredentialCreationOptions where challenge=?",[retrievedChallenge])[0]
    except:
        return jsonify({"Error:","Could not find challenge"}),500
    #DELETE from table
    database.delete_db("delete from PublicKeyCredentialCreationOptions where challenge=?",[retrievedChallenge])
    signature = AuthenticatorAttestationResponse['signature']
    assertion_response =  {'clientData':AuthenticatorAttestationResponse['clientDataJSON'],'authData':AuthenticatorAttestationResponse['authenticatorData'],'signature':signature,'userHandle':AuthenticatorAttestationResponse['userHandle']}

    credential_id = AuthenticatorAttestationResponse.get('id')
    user = database.query_db("select * from Users where credential_id=?",[credential_id])[0]
    if len(user)==0:
        return make_response(jsonify({'fail': 'User does not exist.'}), 401)
    webauthn_user = webauthn.WebAuthnUser(
        user[0], user[0], user[2], user[6],
        user[4], user[3], user[5], user[7])

    webauthn_assertion_response = webauthn.WebAuthnAssertionResponse(
        webauthn_user,
        assertion_response,
        retrievedChallenge,
        ORIGIN,
        uv_required=False)  # User Verification
    sign_count = webauthn_assertion_response.verify()
    try:
        sign_count = webauthn_assertion_response.verify()
    except Exception as e:
        print(e)
        return make_response(jsonify({'fail': 'Assertion failed'}),500)

    # Update counter.

    #Update database
    update = database.insert_db("update Users SET sign_count=? where username=?",[sign_count,user[1]])
    identityObj={'username':user[1],'id':user[0],'displayname':user[2]}
    expires = datetime.timedelta(hours=2)
    print(identityObj)
    jwt = create_access_token(identity=identityObj,expires_delta=expires)
    return jsonify({
        'success':
        'Successfully authenticated as {}'.format(user[1]),
        'jwt':jwt,
        'username': user[1]
    })
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
Beispiel #15
0
    def webauthn_user(self):
        from judge.jinja2.gravatar import gravatar

        return webauthn.WebAuthnUser(
            user_id=self.user.webauthn_id,
            username=self.user.username,
            display_name=self.user.username,
            icon_url=gravatar(self.user.user.email),
            credential_id=webauthn_decode(self.cred_id),
            public_key=self.public_key,
            sign_count=self.counter,
            rp_id=settings.WEBAUTHN_RP_ID,
        )
Beispiel #16
0
def login_start():
    username = request.json.get('username')
    if username not in USERS:
        return jsonify(status='failure', error='User with given username not found')

    challenge = secrets.token_urlsafe(32)
    session['challenge'] = challenge

    user = USERS[username]
    user_id, username, credential_id, public_key = user['id'], user['username'], user['credential_id'], user['public_key']
    webauthn_user = webauthn.WebAuthnUser(user_id=user_id, username=username, display_name=username, icon_url=ICON_URL, credential_id=credential_id, public_key=public_key, sign_count=0, rp_id=RELYING_PARTY_ID)
    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(webauthn_user, challenge)
    return jsonify(status='success', options=webauthn_assertion_options.assertion_dict)
Beispiel #17
0
    def get_assertion_response(self):
        credential = self.test_validate_registration()
        webauthn_user = webauthn.WebAuthnUser(
            USER_ID, USER_NAME, USER_DISPLAY_NAME, ICON_URL,
            credential.credential_id.decode(), credential.public_key,
            credential.sign_count, credential.rp_id)

        webauthn_assertion_response = webauthn.WebAuthnAssertionResponse(
            webauthn_user,
            copy(ASSERTION_RESPONSE_TMPL),
            ASSERTION_CHALLENGE,
            ORIGIN,
            uv_required=False)

        return webauthn_assertion_response
Beispiel #18
0
    def challenge(self, request, otp_device):
        challenge = generate_challenge()
        request.session['challenge'] = challenge

        ukey = base64.urlsafe_b64encode(str(request.user.id).encode('utf-8'))
        webauthn_user = webauthn.WebAuthnUser(
            ukey, otp_device.user.username, otp_device.user.username,
            otp_device.data['icon_url'], otp_device.data['credential_id'],
            otp_device.data['pub_key'], otp_device.counter,
            otp_device.data['rp_id'])

        webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(
            webauthn_user, challenge)

        return webauthn_assertion_options.assertion_dict
Beispiel #19
0
def webauthn_verify_login():
    '''Verify the user's credential attesttion during the login process'''
    challenge = session['login']['challenge']
    assertion_response = request.form
    credential_id = assertion_response.get('id')

    # Ensure a matching user exists
    user = User.query.filter_by(credential_id=credential_id).first()
    if not user:
        flash('User does not exist')
        return make_response(jsonify({'redirect': url_for('login')}), 401)

    # TODO: determine if this info should be stored at the session level
    webauthn_user = webauthn.WebAuthnUser(
        user_id=user.ukey,
        username=user.email,
        display_name=user.display_name,
        icon_url=user.icon_url,
        credential_id=user.credential_id,
        public_key=user.public_key,
        sign_count=user.sign_count,
        rp_id=user.rp_id,
    )

    webauthn_assertion_response = webauthn.WebAuthnAssertionResponse(
        webauthn_user=webauthn_user,
        assertion_response=assertion_response,
        challenge=challenge,
        origin=ORIGIN,
        uv_required=False,
    )  # User Verification

    try:
        sign_count = webauthn_assertion_response.verify()
    except Exception as e:
        flash(f'Assertion failed. Error: {e}')
        return make_response(jsonify({'redirect': url_for('login')}), 401)

    # Update counter.
    user.sign_count = sign_count
    db.session.add(user)
    db.session.commit()

    # Clear login session info
    session.pop('login', None)

    login_user(user)
    return jsonify({'redirect': url_for('profile')})
Beispiel #20
0
 def webauthnuser(self):
     d = json.loads(self.json_data)
     # We manually need to convert the pubkey from DER format (used in our
     # former U2F implementation) to the format required by webauthn. This
     # is based on the following example:
     # https://www.w3.org/TR/webauthn/#sctn-encoded-credPubKey-examples
     pub_key = pub_key_from_der(
         websafe_decode(d['publicKey'].replace('+', '-').replace('/', '_')))
     pub_key = binascii.unhexlify(
         'A5010203262001215820{:064x}225820{:064x}'.format(
             pub_key.public_numbers().x,
             pub_key.public_numbers().y))
     return webauthn.WebAuthnUser(d['keyHandle'], self.user.email,
                                  str(self.user),
                                  settings.SITE_URL, d['keyHandle'],
                                  websafe_encode(pub_key), 1,
                                  urlparse(settings.SITE_URL).netloc)
Beispiel #21
0
def webauthn_begin_transfer():
    amount = request.form.get('transfer_amount')
    recipient = request.form.get('transfer_recipient')

    if not util.validate_transfer_amount(amount):
        return make_response(jsonify({'fail': 'Invalid transfer amount.'}),
                             401)

    # Make the amount into an int type. Type safety assured by `util.validate_transfer_amount`
    amount = int(amount)

    # Extract the logged in `g.user`
    person = g.user.person

    if not person:
        return make_response(jsonify({'fail': 'User does not exist.'}), 401)
    if not person.credential_id:
        return make_response(jsonify({'fail': 'Unknown credential ID.'}), 401)

    session.pop('challenge', None)
    session.pop('transfer_amount', None)
    session.pop('transfer_recipient', None)
    session.pop('clientExtensions', None)

    challenge = util.generate_challenge(32)

    # We strip the padding from the challenge stored in the session
    # for the reasons outlined in the comment in webauthn_begin_activate.
    session['challenge'] = challenge.rstrip('=')
    session['transfer_amount'] = amount
    session['transfer_recipient'] = recipient
    session['clientExtensions'] = {
        'txAuthSimple':
        "Authorize sending {} coins from {} to {}!".format(
            amount, person.username, recipient)
    }

    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_options = webauthn.WebAuthnAssertionOptions(
        webauthn_user, challenge, clientExtensions=session['clientExtensions'])

    return jsonify(webauthn_assertion_options.assertion_dict)
Beispiel #22
0
def _get_webauthn_users(user, *, icon_url, rp_id):
    """
    Returns a webauthn.WebAuthnUser instance corresponding
    to the given user model, with properties suitable for
    usage within the webauthn API.
    """
    return [
        pywebauthn.WebAuthnUser(
            str(user.id),
            user.username,
            user.name,
            icon_url,
            credential.credential_id,
            credential.public_key,
            credential.sign_count,
            rp_id,
        ) for credential in user.webauthn
    ]
Beispiel #23
0
def webauthn_begin_assertion(request):
    print("webauthn_begin_assertion")
    username = request.POST.get('login_username')
    challenge = generate_challenge(32)
    user = User.objects.get(username=username)
    if 'challenge' in request.session:
        del request.session['challenge']

    challenge = generate_challenge(32)
    print("assertion get challenge")
    request.session['challenge'] = challenge
    webauthn_user = webauthn.WebAuthnUser(
        user.ukey, user.username, user.display_name, user.icon_url,
        user.credential_id, user.pub_key, user.sign_count, user.rp_id)
    print("assertion get user")
    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(
        webauthn_user, challenge)
    print("go return")
    return JsonResponse(webauthn_assertion_options.assertion_dict)
Beispiel #24
0
def verify_assertion(election):
    challenge = session.get('challenge')
    assertion_response = request.form
    credential_id = assertion_response.get('id')

    user = Authority.query.filter(
        Election.name == election,
        Authority.credential_id == credential_id).first()
    if not user:
        return make_response(jsonify({'fail': 'User does not exist.'}), 401)

    webauthn_user = webauthn.WebAuthnUser(user.ukey, user.email, user.name,
                                          user.icon_url, user.credential_id,
                                          user.pub_key, user.sign_count,
                                          user.rp_id)

    http = request.url.split("://")
    origin = f"{http[0]}://{election}.{ORIGIN}"

    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 jsonify({'fail': 'Assertion failed. Error: {}'.format(e)})

    # Update counter
    user.sign_count = sign_count
    db.session.add(user)
    db.session.commit()

    login_user(user)

    return jsonify(
        {'success': 'Successfully authenticated as {}'.format(user.email)})
Beispiel #25
0
def auth_request():
    username = request.form.get('login_username')

    user = User.query.filter_by(username=username).first()

    if 'challenge' in session:
        del session['challenge']

    challenge = util.generate_challenge(32)

    session['challenge'] = challenge

    webauthn_user = webauthn.WebAuthnUser(user.ukey, user.username,
                                          user.display_name, user.icon_url,
                                          user.credential_id, user.pub_key,
                                          user.sign_count, user.rp_id)

    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(
        webauthn_user, challenge)
    print(webauthn_assertion_options)
    print(webauthn_assertion_options.assertion_dict)
    return json.jsonify(webauthn_assertion_options.assertion_dict)
def login_webauthn_user_begin_assertion(request):
    current_site_details = get_current_site(request)
    username = request.POST["username"]
    webauthn_user = WebAuthnProfile.objects.filter(
        user__username=username).first()
    if webauthn_user is None:
        return JsonResponse({"error": "User doesn't exist"})
    assertion_challenge = token_urlsafe_without_stripping(32)
    request.session["challenge"] = assertion_challenge.rstrip('=')
    generated_webauthn_user = webauthn.WebAuthnUser(
        user_id=webauthn_user.webauthn_ukey,
        username=webauthn_user.user.username,
        display_name=webauthn_user.display_name,
        credential_id=webauthn_user.credential_id,
        icon_url=
        "https://rajeevkr.me/assets/img/portfolio/IMG_20180302_232843.jpg",
        public_key=webauthn_user.user_public_key,
        sign_count=webauthn_user.signature_counter,
        rp_id=current_site_details.domain.split(":")[0])
    generated_webauthn_user_assertion = webauthn.WebAuthnAssertionOptions(
        generated_webauthn_user, assertion_challenge)
    return JsonResponse(generated_webauthn_user_assertion.assertion_dict)
Beispiel #27
0
def login_start():
    username, password = request.json.get('username'), request.json.get('password')
    if username not in ADMIN_USERS:
        logger.info(f"Login start failed: no user with username {username}")
        return jsonify(status='failure', error='User with given username not found')
    user = ADMIN_USERS[username]
    if not isinstance(password, str) or not check_password_hash(user.password_hash, password):
        logger.info(f"Login start failed: incorrect password")
        return jsonify(status='failure', error='Incorrect password')
    logger.info(f"Login started for user {username} with password hash {user.password_hash}: password correct")

    if DISABLE_ADMIN_WEBAUTHN:
        logger.info(f"Login completed for user {username} (DISABLE_ADMIN_WEBAUTHN is enabled)")
        login_user(user, remember=False)
        return jsonify(status='success', options={})

    challenge = secrets.token_urlsafe(32)
    session['challenge'] = challenge
    webauthn_user = webauthn.WebAuthnUser(user_id=user.id, username=user.username, display_name=user.username, icon_url=ICON_URL, credential_id=user.credential_id, public_key=user.public_key, sign_count=0, rp_id=RELYING_PARTY_ID)
    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(webauthn_user, challenge)
    logger.info(f"Login challenge issued for user {username} with challenge {challenge}")
    return jsonify(status='success', options=webauthn_assertion_options.assertion_dict)
Beispiel #28
0
def webauthn_login_start():
    '''Start the biometric login process by generating a random challenge for the user'''
    email = request.form['email']

    if not validate_email(email):
        flash('Please enter a valid email', 'error')
        return make_response(jsonify({'redirect': url_for('login')}), 401)

    # Attempt to find user in database
    user = User.query.filter_by(email=email).first()
    if not user:
        flash('User does not exist', 'error')
        return make_response(jsonify({'redirect': url_for('login')}), 401)
    if not user.credential_id:
        flash('User does not have biometric to sign in with', 'error')
        return make_response(jsonify({'redirect': url_for('login')}), 401)

    # We strip the padding from the challenge stored in the session
    # for the reasons outlined in the comment in webauthn_begin_activate.
    challenge = secrets.token_urlsafe(32)
    session['login'] = {'challenge': challenge.rstrip('=')}

    webauthn_user = webauthn.WebAuthnUser(
        user_id=user.ukey,
        username=user.email,
        display_name=user.display_name,
        icon_url=user.icon_url,
        credential_id=user.credential_id,
        public_key=user.public_key,
        sign_count=user.sign_count,
        rp_id=user.rp_id,
    )

    webauthn_assertion_options = webauthn.WebAuthnAssertionOptions(
        webauthn_user, challenge
    )

    return jsonify(webauthn_assertion_options.assertion_dict)
Beispiel #29
0
    def verify(self, request, otp_device, data):
        challenge = request.session.get('challenge', '').rstrip('=')

        ukey = base64.urlsafe_b64encode(str(request.user.id).encode('utf-8'))
        webauthn_user = webauthn.WebAuthnUser(
            ukey, otp_device.user.username, otp_device.user.username,
            otp_device.data['icon_url'], otp_device.data['credential_id'],
            otp_device.data['pub_key'], otp_device.counter,
            otp_device.data['rp_id'])

        webauthn_assertion_response = webauthn.WebAuthnAssertionResponse(
            webauthn_user,
            data,
            challenge,
            self._get_origin(request),
            uv_required=False)  # User Verification
        try:
            sign_count = webauthn_assertion_response.verify()
        except AuthenticationRejectedException as e:
            raise ValidationError(str(e))
        otp_device.counter = sign_count
        otp_device.save()
        return {}
Beispiel #30
0
def verify_assertion():
    challenge = session['challenge']
    assertion_response = request.form
    credential_id = assertion_response.get('id')
    publickey_redential = PublicKeyCredential.query.filter_by(
        credential_id=credential_id).first()
    if not publickey_redential:
        return make_response(
            jsonify({
                "status": "failed",
                "msg": "No pubkey found"
            }), 401)
    user = publickey_redential.user
    name = publickey_redential.email
    webauthn_user = webauthn.WebAuthnUser(publickey_redential.ukey, name,
                                          user.display_name, "", credential_id,
                                          publickey_redential.pub_key, 0,
                                          publickey_redential.rp_id)
    webauthn_assertion_response = webauthn.WebAuthnAssertionResponse(
        webauthn_user,
        assertion_response,
        challenge,
        request.host_url[:-1],
        uv_required=False)
    try:
        webauthn_assertion_response.verify()
    except Exception as e:
        return make_response(
            jsonify({
                'status': 'failed',
                'msg': '{}'.format(e)
            }), 401)
    session['register_username'] = name
    session['register_display_name'] = user.display_name
    session['register_ukey'] = publickey_redential.ukey
    login_user(user)
    return jsonify({"status": "success"})