0

When I run the code and enter a password that's old and hasn't been hashed it tells me that it is tuple which isn't the problem but when I try to verify a hashed password I get that my password is wrong so I wonder what's wrong with my code. I'm new to python and not super experienced with mysql but I think the problem lies at how I select the hashed password and do the if statement.

'''

from flask import Flask, render_template, request, redirect, url_for, session
from flask_mysqldb import MySQL
from passlib.hash import sha256_crypt
import MySQLdb.cursors
import re
import hashlib
import os

salt = os.urandom(32)


app = Flask(__name__)

app.secret_key = 'ý{Hå<\x95ùã\x96.5Ñ\x01O<!Õ¢\xa0\x9fR"¡¨'

# Enter your database connection details below
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = ''
app.config['MYSQL_DB'] = 'pythonlogin'

# Intialize MySQL
mysql = MySQL(app)

@app.route('/pythonlogin/', methods=['GET', 'POST'])
def login():
    # Output message if something goes wrong...
    msg = ''
    # Check if "username" and "password" POST requests exist (user submitted form)
    if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
        # Create variables for easy access
        username = request.form['username']
        password = request.form['password']

        # Check if account exists using MySQL
        cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute('SELECT * FROM accounts WHERE username = %s AND password = %s', (username, password,))
        # Fetch one record and return result
        account = cursor.fetchone()
        hashedPass = ('SELECT password FROM accounts WHERE username = %s', (username))
        # If account exists in accounts table in out database
        if account and sha256_crypt.verify(password, hashedPass):
            # Create session data, we can access this data in other routes
            session['loggedin'] = True
            session['id'] = account['id']
            session['username'] = account['username']
            # Redirect to home page
            return redirect(url_for('home'))
        else:
            # Account doesnt exist or username/password incorrect
            msg = 'Incorrect username/password!'
    # Show the login form with message (if any)
    return render_template('index.html', msg=msg)

''' This above is where I believe the problem is hashtags/comments are because I've followed a tutorial to learn and now I try to build onto it which is where I'm now stuck

This is how I hash it and I believe that's it's done correctly: '''

@app.route('/pythonlogin/register', methods=['GET', 'POST'])
def register():
    # Output message if something goes wrong...
    msg = ''
    # Check if "username", "password" and "email" POST requests exist (user submitted form)
    if request.method == 'POST' and 'username' in request.form and 'password' in request.form and 'email' in request.form:
        # Create variables for easy access
        username = request.form['username']
        password = sha256_crypt.encrypt(request.form['password']) #Sha 256 encryptering med hash och salt
        email = request.form['email']

        # Check if account exists using MySQL
        cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute('SELECT * FROM accounts WHERE username = %s', (username,))
        account = cursor.fetchone()
        # If account exists show error and validation checks
        if account:
            msg = 'Account already exists!'
        elif not re.match(r'[^@]+@[^@]+\.[^@]+', email):
            msg = 'Invalid email address!'
        elif not re.match(r'[A-Za-z0-9]+', username):
            msg = 'Username must contain only characters and numbers!'
        elif not username or not password or not email:
            msg = 'Please fill out the form!'
        else:
            # Account doesnt exists and the form data is valid, now insert new account into accounts table

            cursor.execute('INSERT INTO accounts VALUES (NULL, %s, %s, %s)', (username, password, email,))
            mysql.connection.commit()
            msg = 'You have successfully registered!'

'''

I can see in the database that users gets registered with a hashed and salted password. Thanks for any help :)

Gabe
  • 1
  • 1
  • This is wrong: `cursor.execute('SELECT * FROM accounts WHERE username = %s AND password = %s', (username, password,))` - this should never match and will return no data. Don't search for the crypted password; it could hash to a different value. Only use .verify to check if they are equivalent. – Joe Mar 22 '21 at 20:33
  • Oh okay, thanks a lot Joe for your reply, how would I go about checking if the enetered password matches with the encrypted one then? – Gabe Mar 22 '21 at 20:42
  • That's what ` if account and sha256_crypt.verify(password, hashedPass):` is doing in the first code example – Joe Mar 22 '21 at 21:00
  • Oh yeah I know, I phrased that question poorly, I edited the code you pointed out to this: 'SELECT * FROM accounts WHERE username = %s', (username))' but it still doesn't work but it's giving me another error message "not all arguments converted during bytes formatting" so there is still something wrong and I guess its about the account variable since I'm not exactly sure what it does. It has to be to connect the user to it since otherwise it would only look at if a password was correct? – Gabe Mar 22 '21 at 21:20
  • I find that when I do 'SELECT password FROM accounts WHERE username = %s', (username) it actually doesn't select the encrypted password as I thought but, it rathergets assigned to that exact string. – Gabe Mar 22 '21 at 22:14

1 Answers1

0

Ok so I figured out how I should do the verification and now it works like butter:

cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute("SELECT * FROM accounts WHERE username = %s", (username,))
        # Fetch one record and return result
        account = cursor.fetchone()
        validatePassword = sha256_crypt.verify(password, account['password'])
        # If account exists in accounts table in out database
        if account and validatePassword:

Correct me if I'm missing something but I believe it's done :)

Gabe
  • 1
  • 1