Search code examples
pythonflaskflask-sqlalchemy

Flask doesnt login after updated password


I trying to create a way to update users password in Flask, but for some reason unkown to me after the update the user cant login again. It says the password is incorrect, I cant see what might be wrong any help would be appreciated

Below my route, I'm using bcrypt to hash the password. I also tried to decode it to utf8 but it doesnt help:

@app.route('/change-password', methods=['GET', 'POST'])
@login_required
def change_password():
    if request.method == 'POST':
        current_password = request.form.get('current_password')
        new_password = request.form.get('new_password')
        confirm_password = request.form.get('confirm_password')

        if new_password != confirm_password:
            flash('As novas senhas não coincidem.')
            return redirect(url_for('change_password'))

        user_password_hash = get_user_password_hash(current_user.id)

        if not bcrypt.check_password_hash(user_password_hash, current_password):
            flash('Senha atual incorreta.')
            return redirect(url_for('change_password'))

        hashed_password = bcrypt.generate_password_hash(new_password)
        update_user_password(current_user.id, hashed_password)
        flash('Senha atualizada com sucesso.')
        return redirect(url_for('index'))

    return render_template('home/change_password.html')

def get_user_password_hash(user_id):
    user = User.query.get(user_id)
    return user.pwd

def update_user_password(user_id, new_password):
    user = User.query.get(user_id)
    if user:
        user.pwd = bcrypt.generate_password_hash(new_password)
        db.session.commit()

This is the change_password.html:

<!DOCTYPE html>
<html>
<head>
    <title>Troca de Senha</title>
</head>
<body>
    <h1>Troca de Senha</h1>
    {% for message in get_flashed_messages() %}
        <p>{{ message }}</p>
    {% endfor %}
    <form method="POST" action="{{ url_for('change_password') }}">
        <label for="current_password">Senha Atual:</label>
        <input type="password" id="current_password" name="current_password" required><br><br>

        <label for="new_password">Nova Senha:</label>
        <input type="password" id="new_password" name="new_password" required><br><br>

        <label for="confirm_password">Confirme a Nova Senha:</label>
        <input type="password" id="confirm_password" name="confirm_password" required><br><br>

        <input type="submit" value="Trocar Senha">
    </form>
</body>
</html>

Solution

  • You are double-hashing the password.

    This function:

    def update_user_password(user_id, new_password):
        user = User.query.get(user_id)
        if user:
            user.pwd = bcrypt.generate_password_hash(new_password)
            db.session.commit()
    

    Takes new_password as an argument. That should be the plaintext that the user entered. But that's not what you're passing:

    hashed_password = bcrypt.generate_password_hash(new_password)
    update_user_password(current_user.id, hashed_password)
    

    You already hash it, then pass the hash to the function that hashes it again (or, rather, generates a hash of the previous hash).