示例#1
0
def request_password_reset():
    data = request.json
    if not data:
        return abort(make_response(jsonify(message="Missing payload"), 400))
    email = data.get("email", "").lstrip().rstrip().lower()
    if not email or not is_email(email):
        return abort(
            make_response(jsonify(message="Missing or bad email"), 400))
    existing = users.get_by_email(email)
    # we are not leaking used or unused e-mails, that's why this responds 202
    if not existing or existing["activated"] is None:
        return "", 202
    local = local_users.get_local_user(existing["uuid"])
    if not local:
        return abort(
            make_response(jsonify(message="User does not have a password"),
                          400))
    pwd_reset_key = guid.uuid4()
    pwd_reset_key_expires = datetime.now().astimezone() + timedelta(hours=1)
    local_users.update_local_user(
        user_uuid=existing["uuid"],
        pwd_reset_key_hash=hashlib.sha256(
            str(pwd_reset_key).encode("utf-8")).hexdigest(),
        pwd_reset_key_expires=pwd_reset_key_expires,
    )
    send_mail.delay(
        [email],
        "PASSWORD_RESET_LINK",
        {
            "pwd_reset_key": pwd_reset_key,
            "pwd_reset_key_expires": int(pwd_reset_key_expires.timestamp()),
            "email": email,
        },
    )
    return "", 202
示例#2
0
def reset_password():
    data = request.json
    if not data:
        return abort(make_response(jsonify(message="Missing payload"), 400))
    email = data.get("email", "").lstrip().rstrip().lower()
    pwd_reset_key = data.get("pwd_reset_key", None)
    password = data.get("password", None)
    password_confirmation = data.get("password_confirmation", None)

    try:
        validate_email(email, check_deliverability=False)
    except EmailNotValidError as e:
        return abort(
            make_response(jsonify(message=f"Email not valid: {e}"), 400))
    if not password:
        return abort(make_response(jsonify(message="Missing password"), 400))
    if not pwd_reset_key:
        return abort(make_response(jsonify(message="Missing reset key"), 400))
    if password != password_confirmation:
        return abort(make_response(jsonify(message="Password mismatch"), 400))

    existing = users.get_by_email(email)
    if not existing:
        return abort(make_response(jsonify(message="Cannot reset"), 400))
    local = local_users.get_local_user(existing["uuid"])
    if not local:
        return abort(
            make_response(jsonify(message="User does not have a password"),
                          400))

    if (hashlib.sha256(str(pwd_reset_key).encode("utf-8")).hexdigest() !=
            local["pwd_reset_key_hash"]):
        return abort(make_response(jsonify(message="Cannot reset"), 400))
    if local["pwd_reset_key_expires"] < datetime.now().astimezone():
        return abort(make_response(jsonify(message="Reset key expired"), 400))

    pwd_hash = bcrypt.hashpw(password.encode("utf8"), bcrypt.gensalt())
    local_users.update_local_user(
        user_uuid=existing["uuid"],
        pwd_hash=pwd_hash.decode("utf8"),
        pwd_reset_key_hash=None,
        pwd_reset_key_expires=None,
        force_pwd_change=False,
    )
    send_mail.delay(
        [email],
        "PASSWORD_RESET_CONFIRMATION",
        {
            "email": email,
        },
    )
    return "", 204
示例#3
0
def change_password():
    data = request.json
    if not data:
        return abort(make_response("", 400))
    password = data.get("password", None)
    new_password = data.get("new_password", None)
    new_password_confirmation = data.get("new_password_confirmation", None)
    if (not password or not new_password or not new_password_confirmation
            or new_password != new_password_confirmation):
        return abort(make_response("", 400))

    user = get_current_user()
    if not user:
        return abort(make_response("", 401))

    local = local_users.get_local_user(user["uuid"])
    if not local:
        return abort(make_response("", 401))

    if not bcrypt.checkpw(password.encode("utf8"),
                          local["pwd_hash"].encode("utf8")):
        return abort(make_response("", 401))

    pwd_hash = bcrypt.hashpw(new_password.encode("utf8"), bcrypt.gensalt())
    local_users.update_local_user(pwd_hash=pwd_hash.decode("utf8"),
                                  force_pwd_change=False,
                                  user_uuid=user["uuid"])
    userdata = dict(user)

    response = jsonify({
        "identity":
        userdata.get("uuid", None),
        "role":
        userdata.get("role", "user"),
        "username":
        userdata.get("username"),
        "force_pwd_change":
        userdata.get("force_pwd_change", False),
        "fresh":
        True,
        "expires_on":
        datetime.now() + ACCESS_TOKEN_EXPIRES_AFTER,
    })
    access_token = create_access_token(
        identity=userdata,
        fresh=True,
        expires_delta=ACCESS_TOKEN_EXPIRES_AFTER)
    set_access_cookies(response, access_token)
    return response, 200
示例#4
0
def authenticate_base(include_refresh_token):
    data = request.json
    if not data:
        return abort(make_response(jsonify(message="Missing payload"), 400))
    username = data.get("username", None)
    password = data.get("password", None)
    if not username or not password:
        raise BadRequest("Missing username or password in request body.")
    user = users.get_by_email(username.lstrip().rstrip().lower())
    # fallback to legacy username login
    if not user:
        user = users.get_by_username(username)
    if not user:
        raise Unauthorized("Invalid credentials.")

    if user["suspended"]:
        raise Unauthorized("Account suspended")

    local = local_users.get_local_user(user["uuid"])
    if not local:
        raise Unauthorized("Invalid credentials.")
    if not bcrypt.checkpw(password.encode("utf8"),
                          local["pwd_hash"].encode("utf8")):
        raise Unauthorized("Invalid credentials.")
    # drop reset pwd key if any
    if local["pwd_reset_key_hash"]:
        local_users.update_local_user(uuid=user["uuid"],
                                      pwd_reset_key_hash=None,
                                      pwd_reset_key_expires=None)

    userdata = dict(user)
    userdata.update(local)
    response = jsonify(get_user_identity(userdata, True))
    access_token = create_access_token(
        identity=userdata,
        fresh=True,
        expires_delta=ACCESS_TOKEN_EXPIRES_AFTER)
    set_access_cookies(response, access_token)
    if include_refresh_token:
        refresh_token = create_refresh_token(
            identity=userdata, expires_delta=REFRESH_TOKEN_EXPIRES_AFTER)
        set_refresh_cookies(response, refresh_token, 7 * 24 * 60 * 60)
    return response, 200
示例#5
0
def change_password():
    data = request.json
    if not data:
        return abort(make_response(jsonify(message="Missing payload"), 400))
    password = data.get("password", None)
    new_password = data.get("new_password", None)
    new_password_confirmation = data.get("new_password_confirmation", None)
    if (not password or not new_password or not new_password_confirmation
            or new_password != new_password_confirmation):
        return abort(make_response(jsonify(message="Password issues"), 400))

    user = get_current_user()
    if not user:
        return abort(make_response(jsonify(message="Unauthorized"), 401))

    local = local_users.get_local_user(user["uuid"])
    if not local:
        return abort(make_response(jsonify(message="Unauthorized"), 401))

    if not bcrypt.checkpw(password.encode("utf8"),
                          local["pwd_hash"].encode("utf8")):
        return abort(make_response(jsonify(message="Unauthorized"), 401))

    pwd_hash = bcrypt.hashpw(new_password.encode("utf8"), bcrypt.gensalt())
    local_users.update_local_user(pwd_hash=pwd_hash.decode("utf8"),
                                  force_pwd_change=False,
                                  user_uuid=user["uuid"])
    userdata = dict(user)

    response = jsonify(get_user_identity(userdata, True))
    access_token = create_access_token(
        identity=userdata,
        fresh=True,
        expires_delta=ACCESS_TOKEN_EXPIRES_AFTER)
    set_access_cookies(response, access_token)
    return response, 200