ASP.NET ID Change Password

I need to change the password for the admin user. Thus, the administrator should not enter the current user password, he should be able to set a new password. I am looking at the ChangePasswordAsync method, but the old password is required for this method. Therefore, this method is not suitable for this task. So I did it like this:

[HttpPost] public async Task<ActionResult> ChangePassword(ViewModels.Admin.ChangePasswordViewModel model) { var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); var result = await userManager.RemovePasswordAsync(model.UserId); if (result.Succeeded) { result = await userManager.AddPasswordAsync(model.UserId, model.Password); if (result.Succeeded) { return RedirectToAction("UserList"); } else { ModelState.AddModelError("", result.Errors.FirstOrDefault()); } } else { ModelState.AddModelError("", result.Errors.FirstOrDefault()); } return View(model); } 

It works, but theoretically we can get an error in the AddPasswordAsync method. Thus, the old password will be deleted, but the new one will not be set. This is not good. Any way to do this in a "single transaction"? PS. I saw the ResetPasswordAsync method with the reset token, it seems to be more secure (because it cannot be an unstable situation with the user), but in any case it performs 2 actions.

+49
c # asp.net-mvc-5 asp.net-identity-2 reset-password
Mar 27 '15 at 0:36
source share
10 answers

ApplicationUserManager is a class generated by an ASP.NET template.

This means that you can edit it and add any functions that it does not have yet. The UserManager class has a protected property called Store , which stores a reference to the UserStore class (or any subclass of it, depending on how you set up your ASP.NET authentication or if you use custom user repository implementations, i.e. if you use a different database engine (e.g. MySQL).

 public class AplicationUserManager : UserManager<....> { public async Task<IdentityResult> ChangePasswordAsync(TKey userId, string newPassword) { var store = this.Store as IUserPasswordStore; if(store==null) { var errors = new string[] { "Current UserStore does not implement IUserPasswordStore" }; return Task.FromResult<IdentityResult>(new IdentityResult(errors) { Succeeded = false }); } if(PasswordValidator != null) { var passwordResult = await PasswordValidator.ValidateAsync(password); if(!password.Result.Success) return passwordResult; } var newPasswordHash = this.PasswordHasher.HashPassword(newPassword); await store.SetPasswordHashAsync(userId, newPasswordHash); return Task.FromResult<IdentityResult>(IdentityResult.Success); } } 

UserManager is nothing more than a wrapper for the underlying UserStore . Check out the documentation on the IUserPasswordStore interface on MSDN for available methods.

Edit: PasswordHasher also a public property of the UserManager class, see interface definition here .

Edit 2: Since some people naively believe that you cannot perform a password check this way, I updated it. The PasswordValidator property is also a UserManager property and is as simple as adding 2 lines of code to add password verification (although this was not a requirement of the original question).

+33
Mar 27 '15 at 0:56
source share

This method worked for me:

 public async Task<IHttpActionResult> changePassword(UsercredentialsModel usermodel) { ApplicationUser user = await AppUserManager.FindByIdAsync(usermodel.Id); if (user == null) { return NotFound(); } user.PasswordHash = AppUserManager.PasswordHasher.HashPassword(usermodel.Password); var result = await AppUserManager.UpdateAsync(user); if (!result.Succeeded) { //throw exception...... } return Ok(); } 
+52
Dec 24 '15 at
source share

EDIT: I know that the OP requested an answer that performs the task in one transaction, but I think the code is useful to people.

All answers use PasswordHasher directly, which is not a good idea, since you will lose some baked functionality (validation, etc.).

An alternative (and I would suggest the recommended approach) is to create a reset password, and then use it to change the password. Example:

 var user = await UserManager.FindByIdAsync(id); var token = await UserManager.GeneratePasswordResetTokenAsync(user); var result = await UserManager.ResetPasswordAsync(user, token, "MyN3wP@ssw0rd"); 
+46
Aug 16 '17 at 14:07 on
source share

This is just a refinement of the answer provided by @Tseng. (I had to configure it to make it work).

 public class AppUserManager : UserManager<AppUser, int> { . // standard methods... . public async Task<IdentityResult> ChangePasswordAsync(AppUser user, string newPassword) { if (user == null) throw new ArgumentNullException(nameof(user)); var store = this.Store as IUserPasswordStore<AppUser, int>; if (store == null) { var errors = new string[] { "Current UserStore doesn't implement IUserPasswordStore" }; return IdentityResult.Failed(errors); } var newPasswordHash = this.PasswordHasher.HashPassword(newPassword); await store.SetPasswordHashAsync(user, newPasswordHash); await store.UpdateAsync(user); return IdentityResult.Success; } } 

Note. This only applies to the modified setting, which uses int as the primary keys for users and roles. I believe that it would just be necessary to remove args <AppUser, int> to make it work with the default ASP.NET installation.

+6
Jun 16 '16 at 17:48
source share
 public async Task<IActionResult> ChangePassword(ChangePwdViewModel usermodel) { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); var user = await _userManager.FindByIdAsync(userId); var result = await _userManager.ChangePasswordAsync(user, usermodel.oldPassword, usermodel.newPassword); if (!result.Succeeded) { //throw exception...... } return Ok(); } public class ChangePwdViewModel { [DataType(DataType.Password), Required(ErrorMessage ="Old Password Required")] public string oldPassword { get; set; } [DataType(DataType.Password), Required(ErrorMessage ="New Password Required")] public string newPassword { get; set; } } 

Note: here I retrieve the UserId from the current user.

+2
Nov 16 '17 at 3:07 on
source share

If you do not have a current user password and you still want to change the password. What you can do instead is first remove the user password and then add a new password. Thus, you can change the password of a user without having to enter the current password of that user.

 await UserManager.RemovePasswordAsync(user); await UserManager.AddPasswordAsync(user, model.Password); 
+1
Jul 04 '19 at 9:42 on
source share
 public async Task<ActionResult> ChangePassword(ResetPasswordViewModel CP) { ApplicationDbContext context = new ApplicationDbContext(); UserStore<ApplicationUser> store = new UserStore<ApplicationUser>(context); UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(store); var user = await UserManager.FindAsync(User.Identity.Name, CP.CurrentPassword); if (!UserManager.CheckPassword(user, CP.CurrentPassword)) { ViewBag.notification = "Incorrect password."; return View("~/Views/User/settings.cshtml"); } else { if (CP.Password != CP.ConfirmPassword) { ViewBag.notification = "try again"; return View("~/Views/User/settings.cshtml"); } else { String hashedNewPassword = UserManager.PasswordHasher.HashPassword(CP.Password); await store.SetPasswordHashAsync(user, hashedNewPassword); await store.UpdateAsync(user); ViewBag.notification = "successful"; return View("~/Views/User/settings.cshtml"); } } } 
0
Jan 09 '17 at 13:41
source share
  public async Task<List<string>> AsyncModifyPassword(LoginDTO entity) { List<string> errors = new List<string>(); ApplicationUser user = await _userManager.FindByEmailAsync(entity.Email); if (user == null) { errors.Add("User Not Found"); //todo, hablar sobre el tema de lanzar las excepciones return errors; } //user.PasswordHash = _userManager.PasswordHasher.HashPassword(user, entity.Password); IdentityResult result = await _userManager.ChangePasswordAsync(user, entity.Password , entity.NewPassword); if (!result.Succeeded) errors = result.Errors.ToList().Select(error => error.Description).ToList(); return errors; } 
0
Dec 09 '17 at 23:34 on
source share

Try to remove the old password and add a new password.

Code example:

  var userId = System.Web.HttpContext.Current.User.Identity.GetUserId(); if (userId != null) { UserManager<IdentityUser> userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>()); userManager.RemovePassword(userId); String newPassword = "aaaaaaa"; userManager.AddPassword(userId, newPassword); } 

Loans:

@Brando

Recommendations:

UserManager RemovePassword: https://msdn.microsoft.com/en-us/library/dn497511(v=vs.108).aspx

UserManager AddPassword: https://msdn.microsoft.com/en-us/library/dn497465(v=vs.108).aspx

0
Jun 15 '19 at 23:29
source share

Yes you are right. ResetPassword via token is the preferred approach. Once upon a time, I created a complete wrapper on top of .NET Identity and the code can be found here . This may be helpful for you. You can also find nuget here . I also explained the library on the blog here . This shell is easily consumed as nuget and creates all the necessary configurations during installation.

-2
Jul 03 '17 at 17:33
source share



All Articles