Travis Travis - 1 month ago 9
ASP.NET (C#) Question

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);
}

Answer

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:

string hashedPassword = UserManager.PasswordHasher.HashPassword(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.

you can then test hashedPassword against the content of previousPassword1, etc. If they match then the user has entered the same password twice