skip to Main Content

I have created a simple flask authentication

I have deployed it on render

The app runs fine locally

But when in the deployed app, the check_password_hash always returns false

I use mysql on my local machine and the code works fine but it fails when i deploy it on render

I tried changing bcrypt to werkzeug, i checked all the versions on the deployment environment

Registration view

# Registration route
@app.route("/register", methods=["GET", "POST"])
def register():
    if request.method == "POST":
        username = request.form["username"]
        # print(username)-debug
        password = request.form["password"]
        # bytes_register = password.encode("utf-8")
        # print(password)-debug

        # create_table_query_mysql = """
        #     CREATE TABLE IF NOT EXISTS users (
        #         id SMALLINT(5) AUTO_INCREMENT PRIMARY KEY,
        #         username CHAR(128) NOT NULL UNIQUE,
        #         pass_hash CHAR(128) NOT NULL
        #     )
        # """

        create_table_query_postgresql = """
            CREATE TABLE IF NOT EXISTS users (
                id SERIAL PRIMARY KEY,
                username CHAR(255) NOT NULL UNIQUE,
                password_hash CHAR(255) NOT NULL
            )
        """

        existing_user_query = "SELECT * FROM users WHERE username=%s"
        existing_user_username = None

        cursor = connection_db.cursor()
        cursor.execute(create_table_query_postgresql)

        cursor.execute(existing_user_query, (username,))
        existing_user_username = cursor.fetchone()

        if existing_user_username:
            error_message = "Username taken. Please choose a different username"
            return render_template("register.html", error_message=error_message)

        hashed_password = bcrypt.generate_password_hash(password)
        decoded_hashd_password = hashed_password.decode("utf-8")

        insert_user_query = (
            "INSERT INTO users (username, password_hash) VALUES (%s, %s)"
        )
        cursor.execute(insert_user_query, (username, decoded_hashd_password))
        connection_db.commit()
        return render_template("registration_success.html")

    return render_template("register.html")

Login view

# Login Route
@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username_login = request.form["username"]
        password_login = request.form["password"]
        # bytes_login = password_login.encode("utf-8")

        # create_table_query_mysql = """
        #     CREATE TABLE IF NOT EXISTS users (
        #         id SMALLINT(5) AUTO_INCREMENT PRIMARY KEY,
        #         username CHAR(128) NOT NULL UNIQUE,
        #         pass_hash CHAR(128) NOT NULL
        #     )
        # """

        create_table_query_postgresql = """
            CREATE TABLE IF NOT EXISTS users (
                id SERIAL PRIMARY KEY,
                username CHAR(255) NOT NULL UNIQUE,
                password_hash CHAR(255) NOT NULL
            )
        """

        user_query = "SELECT * FROM users WHERE username=%s"
        user_data = None

        cursor = connection_db.cursor()
        cursor.execute(create_table_query_postgresql)
        cursor.execute(user_query, (username_login,))
        user_data = cursor.fetchone()
        hash = user_data[2]
        print(hash)
        print(password_login)
        # hash_bytes = hash.encode("utf-8")
        # print(hash_bytes)
        check = bcrypt.check_password_hash(hash, password_login)
        print(check)

        if user_data and check:
            user = User(id=user_data[0], username=user_data[1])
            login_user(user)
            return redirect("/dashboard")
        else:
            not_valid = "Invalid User"
            return render_template("login.html", not_valid=not_valid)

    return render_template("login.html")

The error causing part is in the login route

       cursor.execute(user_query, (username_login,))
        user_data = cursor.fetchone()
        hash = user_data[2]
        print(hash)
        print(password_login)
        # hash_bytes = hash.encode("utf-8")
        # print(hash_bytes)
        check = bcrypt.check_password_hash(hash, password_login)
        print(check)

2

Answers


  1. Chosen as BEST ANSWER

    The problem in my code is that the i am using CHAR instead of VARCHAR

    The CHAR type in both MySQL and PostgreSQL when defined with a fixed length fills the cell with padding spaces if the string length is less than the fixed length.

    When retrieving data from that cell in postgresql, in my code's case, the password hash, the string is returned with padding spaces which is not visible in the console when printed.

    But when the check_password_hash() checks for the string with padding spaces, it returns false.

    Hence, the check fails.

    MySQL also stores the string with padding spaces in CHAR but removes those spaces during retrieval of the string.

    I was using MySQL in my local machine. Therefore, it worked fine in my local machine but not on the deployment PostgreSQL database.


  2. The error you’re encountering is coming mainly from your registration view, I can see that you inserted the decoded_hashd_password into the database. This in turn causes the error because there is no hash to check against when you run check = bcrypt.check_password_hash(hash, password_login). Try inserting just the hashed_password and not decoded_hashd_password.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search