YAFLogo

knuzich
  • knuzich
  • 51.2% (Neutral)
  • YAF Forumling Topic Starter
15 years ago
It is not possible to recover forgotten password if user changed his password manually once before.

I see error: "Your answer could not be verified. Please try again." every time when i want to recover my password through "recoverpassword" page. Username is correct and answer to password question is correct too and problem does not disappear when i set correct value (for example password answer: "knuzich") instead of variable "answer " in code


protected void PasswordRecovery1_VerifyingAnswer(object sender, LoginCancelEventArgs e)
		{
			e.Cancel = true;
			MembershipUser user = Membership.GetUser(PasswordRecovery1.UserName);
			string answer = PasswordRecovery1.Answer;
			if (user != null)
			{

				if (user.PasswordQuestion.Equals(answer))
				{
					e.Cancel = false;
				}
			}
		}

Every time AnswerLookupError event occures


protected void PasswordRecovery1_AnswerLookupError(object sender, EventArgs e)
		{
			PageContext.AddLoadMessageSession(GetText("QUESTION_FAILURE"));
		}

Any help is greatly appreciated

Sponsor
knuzich
  • knuzich
  • 51.2% (Neutral)
  • YAF Forumling Topic Starter
15 years ago
I have found solution to this problem myself :)

The reason of permanent error is in method "ChangePassword" of class "YafMembershipProvider"



public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
    string salt = string.Empty;
    string str2 = string.Empty;
    if (!this.IsPasswordCompliant(newPassword))
    {
        return false;
    }
    UserPasswordInfo info = UserPasswordInfo.CreateInstanceFromDB(this.ApplicationName, username, false, this.UseSalt, this.HashHex, this.HashCase, this.HashRemoveChars, this.MSCompliant);
    if (info == null)
    {
        return false;
    }
    if (!info.IsCorrectPassword(oldPassword))
    {
        return false;
    }
//here begin
    if (this.UseSalt)
    {
        salt = GenerateSalt();
    }
//here end
    str2 = EncodeString(newPassword, (int) this.PasswordFormat, salt, this.UseSalt, this.HashHex, this.HashCase, this.HashRemoveChars, this.MSCompliant);
    DB.ChangePassword(this.ApplicationName, username, str2, salt, (int) this.PasswordFormat, info.PasswordAnswer);
    return true;
}

Every time in changing user password we generate new value in field "PasswordSalt" but our password question was encoded with previous salt. That is reason why entered "PasswordAnswer" is not equal to saved one in database.

As we can see "DB.ChangePasswordvariable" method saves new value "salt" for current user but does not change encoded password question!!


public static void ChangePassword(string appName, string username, string newPassword, string newSalt, int passwordFormat, string newPasswordAnswer)
		{
			using (SqlCommand command = new SqlCommand(DBAccess.GetObjectName("prov_changepassword")))
			{
				command.CommandType = CommandType.StoredProcedure;
				command.Parameters.AddWithValue("@ApplicationName", appName);
				command.Parameters.AddWithValue("@Username", username);
				command.Parameters.AddWithValue("@Password", newPassword);
				command.Parameters.AddWithValue("@PasswordSalt", newSalt);
				command.Parameters.AddWithValue("@PasswordFormat", passwordFormat);
				command.Parameters.AddWithValue("@PasswordAnswer", newPasswordAnswer);
				DBAccess.ExecuteNonQuery(command);
			}
		}

One should input


if (this.UseSalt && String.IsNullOrEmpty(info.PasswordSalt))
{
	salt = GenerateSalt();
}
else
{
	salt = info.PasswordSalt;
}
instead of marked part (by 'begin here' and 'end here') in code "ChangePassword" method and recopile dll.

Jaben
  • Jaben
  • 100% (Exalted)
  • YAF Developer
15 years ago
Confirmed bug -- thank you -- this bug has been bugging many, many users.

Fix committed to SVN.