Travis
Travis

Reputation: 45

Trying to keep user from using an old password for their new one

I am trying to prevent the user from using any of their last 5 passwords. I am using the exact template from Visual Studio 2015 that gives you a basic Identity user system with it.

I have went ahead to add the following columns to my user database, passwordLastChanged(Date) and 5 columns named previousPassword1 (through 5) respectively.

I need to retreive the current user password from the database using something along the lines of User.Identity.GetUserPassword and I also need something along the lines of model.NewPassword.Encrypt (those don't exist!). Are there methods that do these actions that I am just not seeing in the api?

And I also have to encrypt my new data to see if it matches, how can I encrypt a string the same way that my user password is encrypted?

//
// POST: /Manage/ChangePassword
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ChangePassword(ChangePasswordViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
    var result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
    if (result.Succeeded)
    {
        var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
        if (user != null)
        {
            await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
        }
        return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess });
    }
    AddErrors(result);
    return View(model);
}

Upvotes: 3

Views: 4203

Answers (1)

Liam
Liam

Reputation: 29694

Ok going to turn my comments into some kind of answer. So as mentioned passwords are stored in the table Hashed not encrypted. So by definition they can't be retrived (easily).

There's nothing to stop you putting the hashed passwords into the table though to keep a records of previous passwords. Then when a user enters a password you hash it and check if it's already been used, exactly the same as if it wasn't hashed but using the hash not the raw password (this keeps everything nice and secure too).

I wonder If I can just call a function or if I will have to implement the actual hashing algorithm that uses the same salt and what not?

UserManager implements a PasswordHasher. So to get a password hashed in the same fashion as the default hash should be as simple as:

PasswordVerificationResult passwordMatch = UserManager.PasswordHasher.VerifyHashedPassword(previousPassword1, rawPassword);

I don't use this auth method so the above is untested and based on the MSDN docs only. Should be fine but let me know if it doesn't work.

If the passwords match then passwordMatch == PasswordVerificationResult.Success. You may also need to allow for PasswordVerificationResult.SuccessRehashNeeded

Upvotes: 1

Related Questions