In this Golang Web Development Series we're building a complete Golang HTTP User Authentication System from scratch with the backend MySQL database by using Golang's official MySQL Database Driver. The Golang HTTP Authentication will consist of Golang User Registration, Golang Login Auth, Golang Password Reset, Golang Change Password, Golang Set Cookie, Golang Web Assembly (WASM), Golang Map Token, Golang Persisted Token, etc. with step by step guide here in Golang's Web Development Series.
Get Linode Account:
If you go with extra mile for buying me a cup of coffee, I appreciate it guys:
Source Codes:
api/auth.go:
// ChangePasswordEndpoint is to set a new password from a change password process
func ChangePasswordEndpoint(w http.ResponseWriter, r *http.Request) {
w.Header().Set("content-type", "application/json")
w.WriteHeader(http.StatusOK)
body, errBody := ioutil.ReadAll(r.Body)
if errBody != nil {
itrlog.Error(errBody)
panic(errBody.Error())
}
keyVal := make(map[string]string)
json.Unmarshal(body, &keyVal)
currentPassword := keyVal["currentPassword"]
newPassword := keyVal["password"]
confirmPassword := keyVal["confirmPassword"]
// Open the MySQL DB Connection
dbYabi, err := sql.Open("mysql", DBConStr(""))
if err != nil {
itrlog.Error(err)
}
defer dbYabi.Close()
isNewPasswordSet, err := yabi.ValidateChangePassword(dbYabi, currentPassword, newPassword, confirmPassword)
if err != nil {
itrlog.Error(err)
w.Write([]byte(`{ "IsSuccess": "false", "AlertTitle": "Password Reset Failed!",
"AlertMsg": "` + err.Error() + `", "AlertType": "error", "RedirectURL": "" }`))
return
}
if isNewPasswordSet {
// Response back to the user
w.Write([]byte(`{ "IsSuccess": "true", "AlertTitle": "",
"AlertMsg": "",
"AlertType": "success", "RedirectURL": "` + yabi.YB.BaseURL + `login" }`))
yabi.LogOut(w, r, config.MyEncryptDecryptSK) // Trigger the log-out event
} else {
itrlog.Error(err)
w.Write([]byte(`{ "IsSuccess": "false", "AlertTitle": "Password Change Failed!",
"AlertMsg": "` + err.Error() + `", "AlertType": "error", "RedirectURL": "" }`))
}
}
yabi/user.go:
// ValidateChangePassword validates the current password before committing with the new user's password
func ValidateChangePassword(dbCon *sql.DB, currentPassword, newPassword,
confirmPassword string) (bool, error) {
// Check if current password is empty
if len(strings.TrimSpace(currentPassword)) == 0 {
return false, errors.New("Current Password is Required")
}
// Check if new password is empty
if len(strings.TrimSpace(newPassword)) == 0 {
return false, errors.New("Password is Required")
}
// Check if confirm password is empty
if len(strings.TrimSpace(confirmPassword)) == 0 {
return false, errors.New("Confirm Password is Required")
}
// New and confirm password is not match.
if newPassword != confirmPassword {
return false, errors.New("Password is not Match")
}
// Get the user's stored hash password.
pwHash, err := GetUserPassword(dbCon, YBUserData.UserName)
if err != nil {
return false, errors.New("Oops!, error getting user's credential, please try again")
}
// Now, match the two passwords, check if it's verified or not.
isPassHashMatch, err := sakto.CheckPasswordHash(currentPassword, pwHash)
if err != nil {
return false, errors.New("Oops!, unable to get your user's identity, please try again, thank you")
}
if isPassHashMatch {
// Now, change the password here
isPasswordChange, err := UpdateUserPassword(dbCon, YBUserData.Email, newPassword)
if err != nil {
return false, err
}
if !isPasswordChange {
return false, err
}
}
return true, nil
}
Get the full source codes: