0

In this code, the first function is Findaccount() that will find the email address in the database and the password that is present as a hash. So the CompareHashAndPassword() compares the hash and password.

Now in the handler.go file I have a function called loginData() that will allow the user to log in. I have a problem here. I called database.Findaccount(email, password, hash) function but it just verifies an email address and does not verify the correct password, and give me the false message.

But if I call the function like this database.Findaccount(email, "1234", hash), it verifies both email and password.

How to solve this problem because I won't be able to remember each password.

db.go

func Findaccount(myEmail, myPassword, hash string) bool {
    collection := Connect.Database("WebApp2").Collection("dataStored")
    if err := collection.FindOne(context.TODO(), bson.M{"email": myEmail}).Decode(&Account); err != nil {
        fmt.Println("Enter the correct email or password")
    }
    err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(myPassword))
    return err == nil
}

handler.go

func HashPassword(password string) (string, error) {
    bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
    return string(bytes), err
}

func loginData(w http.ResponseWriter, r *http.Request) {
    email := r.FormValue("email")
    password := r.FormValue("password")
    hash, _ := HashPassword(password)
    match := database.Findaccount(email, password, hash) // here is a problem
    if match == false {
        fmt.Println("false")
    } else {
        fmt.Println("true")
    }
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189

1 Answers1

6

As per documentation, this is the func schema of bycrypt.CompareHashAndPassword():

func CompareHashAndPassword(hashedPassword, password []byte) error

To use that, you need to place the hashedPassword (which is the hashed password that you stored in the db) as the 1st parameter of the function call.

And then okace the password from request param as the value of 2nd parameter.

func loginData(w http.ResponseWriter, r *http.Request) {
    email := r.FormValue("email")
    password := r.FormValue("password")
    match := database.Findaccount(email, password)
    if match == false {
        fmt.Println("false")
    } else {
        fmt.Println("true")
    }
}

func Findaccount(myEmail, myPassword string) bool {
    collection := Connect.Database("WebApp2").Collection("dataStored")
    if err := collection.FindOne(context.TODO(), bson.M{"email": myEmail}).Decode(&Account); err != nil {
        fmt.Println("Enter the correct email or password")
    }
    err := bcrypt.CompareHashAndPassword([]byte(Account.Password), []byte(myPassword))
    return err == nil
}

See on the Findaccount(), the first param of statement bcrypt.CompareHashAndPassword() is filled by Account.Password which is the hashed password stored on the db.

novalagung
  • 10,905
  • 4
  • 58
  • 82
  • 2
    a little bit of salt would be appropriate for that recipe, no ? –  Jul 30 '21 at 08:13
  • @mh-cbon if during the registration process the password is hashed with a salt, then the same salt should be included during the login. from OP question, I've made an assumption that salt is not used at all. might need more details to confirm that. – novalagung Jul 30 '21 at 08:18
  • 1
    yes, i agree. I certainly wanted to open OP eyes about what could be done next. the answer does answer OP, thus, i have plused it. –  Jul 30 '21 at 08:20
  • 6
    @mh-cbon bcrypt includes the salt automatically – zerkms Jul 30 '21 at 08:26
  • @zerkms had no idea it did that.... https://stackoverflow.com/questions/6832445/how-can-bcrypt-have-built-in-salts thank you –  Jul 30 '21 at 08:28