Reputation: 924
I know a similar question has been asked here, but no answer seems to address my problem. I am using Python3, Flask, and flask-bcrypt.
My login function was working fine earlier and I don't believe I changed anything so I'm not sure what happened. The way I understand it is, at signup, we are meant to encode the received password to UTF-8, then decode the hashed password before we pass it to the database as follows:
password = form.password.data.encode('utf-8')
hashed_password = bcrypt.generate_password_hash(password).decode('utf-8')
Then, at login, we are supposed to encode the candidate password and compare that to the hashed password in the database as follows:
password = form.password.data.encode('utf-8')
if bcrypt.check_password_hash(user.password, password):
But i get the error Invalid Salt from this. And I have tried several other variants with no success.
Any help would be greatly appreciated. Here are the views. I can provide any other code necessary.
@app.route('/<role>/signup/', methods=['GET', 'POST'])
def signUp(role):
form = RegisterForm()
if form.validate_on_submit():
password = form.password.data.encode('utf-8')
hashed_password = bcrypt.generate_password_hash(password).decode('utf-8')
new_user = User(role=role, password=hashed_password, visits=1)
form.populate_obj(new_user)
db.session.add(new_user)
db.session.commit()
login_user(new_user)
return redirect(url_for('createContactInfo', user_id=current_user.id))
return render_template('signup.html', form=form, role=role)
@app.route('/login/', methods=['GET', 'POST'])
def logIn():
form = LoginForm()
if form.validate_on_submit():
password = form.password.data.encode('utf-8')
user = User.query.filter_by(email=form.email.data).first()
if user:
if bcrypt.check_password_hash(user.password, password):
login_user(user, remember=form.remember.data)
User.query.filter_by(id=current_user.id).update({'visits': User.visits + 1})
db.session.commit()
if current_user.role == 'admin':
return redirect(url_for('adminMainPage', user_id=current_user.id))
elif current_user.role == 'guest':
return redirect(url_for('guestMainPage', user_id=current_user.id))
else:
return "wrong role!"
flash('Invalid login')
return render_template('login.html', form=form)
flash('Invalid login')
return render_template('login.html', form=form)
return render_template('login.html', form=form)
Upvotes: 1
Views: 2334
Reputation: 924
So I figured it out and the answer really had nothing to do with the question.
The issue was, in signup, I instantiated the object new_user
with password=hashed_password
, but then I called form.populate_obj(new_user)
, which according to the wtforms docs is a destructive operation, and as a result overrode new_user.password
= form.password.data
, which was not hashed.
So I stored the unhashed password in my DB and, at login, I was comparing the hashed candidate password with the unhashed stored password. Hence, Invalid Salt. As discussed in other related matters, the Invalid Salt error is a huge catchall that doesn't really point to the underlying problem.
To fix, I called form.populate_obj(new_user)
first, then added the attributes separately as follows:
new_user = User()
form.populate_obj(new_user)
new_user.role = role
new_user.password = hashed_password
new_user.visits = 1
Upvotes: 1