0

I'm trying to make an authentication system on by backend server based on FastAPI. But I'm currently facing an issue with bcrypt when I try to login the user, the hashed password sent from the user in the post call is never equal to the one stored in the database. This is the code I use to sign up the user:

@app.put('/users')
def createUser(user: createUser):
    salt = bcrypt.gensalt()
    hashed = bcrypt.hashpw(user.password.encode('utf-8'), salt)

    if dbUser.find_one({"username":user.username}) is None:
        user.password = hashed.decode('utf-8')
        print(user)
        dbUser.insert_one(bson.son.SON(user))
        return {"message":"success"}
    else:
        return {"error":"user already exists!"}

when it comes to saving the new user.password. hashed.decode('utf-8') helps me saving a normal string in the database instead of " u'hashed_string' " which I get by doing str(hashed) or Binary("hashed_string", 0) which I get by just saving user.password as hashed withtout str or decode.

The code I use for the login is:

@app.post('/users')
def loginUser(user: loginUser):
    if dbUser.find_one({"username":user.username}) is None:
        return {"error":"user not found"}
    else:
        salt = bcrypt.gensalt()
        hashed = bcrypt.hashpw(user.password.encode('utf-8'), salt)
        dbPassword = dbUser.find_one({"username":user.username})['password'].encode('utf-8')
        if bcrypt.checkpw(dbPassword, hashed):
            return {"message":"success!"}
        else:
            print("does not match")
            return {"message":"wrong password!"}

I am comparing the dbPassowrd encoded, which since it was a string, it will became u'hashed_password' and the hashed and encoded password sent in the post call, which will be u'hashed_password' The issue is that the password sent by the user, once crypted and encoded, is not equal to the one in the database. What am I doing wrong?

Silvano H.
  • 13
  • 4
  • 2
    You're generating a new salt each time, and encrypting the same string with a different salt creates different hashes – C.Nivs Jan 06 '21 at 22:47
  • @C.Nivs is right. I would add that managing the salt explicitly in this way is kind of cumbersome, you have to store it somewhere and retrieve it later to hash the provided password. Considering that **bcrypt handles it automatically** you can skip it completely. See this [SO question](https://stackoverflow.com/questions/6832445/how-can-bcrypt-have-built-in-salts) – Sushi2all Jan 07 '21 at 06:34
  • @Sushi2all so I have to save salt in the database and then crypt the password inserted by the user with the saved salt? And then compare it to the saved password? – Silvano H. Jan 07 '21 at 08:29
  • @SilvanoH. In general yes. But bcrypt embeds the salt in the output string along with the hash, so you don't need to worry about saving it somewhere and retrieving it manually every time. I had the same questions when I started dealing with security issues. Ended up using `passlib` to handle all that, but even bcrypt on its own already manages salts automatically. Check out the discussion I mention above or this [Wikipedia article](https://en.wikipedia.org/wiki/Bcrypt) for more details. – Sushi2all Jan 07 '21 at 09:30
  • @sushi2all Thanks a lot I've just configured the whole system with passlib in 2 minutes – Silvano H. Jan 07 '21 at 10:25

0 Answers0