5

I have implemented the ForgotPassword (with token reset) into my MVC 5 application. We are in production. Although this works in majority of the cases, many of our end-users are of older age and get confused when they cannot login and need a reset. So in those situations, I am considering giving one of our admin staff the ability to reset a user's password and giving them the new password on the phone. The data is not that sensitive.

I tried this:

    public ActionResult ResetPassword()
    {     UserManager<IdentityUser> userManager =
            new UserManager<IdentityUser>(new UserStore<IdentityUser>());

        var user = userManager.FindByEmail("useremail.samplecom");

        userManager.RemovePassword(user.Id);
        userManager.AddPassword(user.Id, "newpassword");
}

I get a cryptic error stating Invalid Column EMail, Invalid Column Email Confirmed ......

I also tried the userManager.ResetPassword(), but abandoned that idea because it needs a token reset. I want to bypass it.

What am I not seeing?

Thanks in advance.

3 Answers 3

5

I also tried the userManager.ResetPassword(), but abandoned that idea because it needs a token reset. I want to bypass it.

How about you just generate the token and pass it to the Reset routine ?

var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
var code = await userManager.GeneratePasswordResetTokenAsync("username");
var result = await userManager.ResetPasswordAsync("username", code, "your new password");
if (!result.Succeeded)
{
    //password does not meet standards
}

The idea here is you are just emulating/bypassing the usual routine of sending the token to the client (via email) and having the link that they click on call ResetPasswordAsync

Sign up to request clarification or add additional context in comments.

1 Comment

This is simple and brilliant. Thanks! For future reference and completeness I had to add this to wal's code: private ApplicationUserManager _userManager; public ApplicationUserManager UserManager { get { return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>(); } private set { _userManager = value; } }
3

I'm not completely sure if this will work in your implementation but I use the following code with success in a use case which has basically the same requirements as yours. The difference is that I'm not letting any user reset it's own password. This is always the task of an admin.

I'm bypassing the ApplicationUserManager and edit the information directly in the table, using just Entity Framework.

// I created an extension method to load the user from the context
// you will load it differently, but just for completeness
var user = db.LoadUser(id);

// some implementation of random password generator
var password = General.Hashing.GenerateRandomPassword();
var passwordHasher = new Microsoft.AspNet.Identity.PasswordHasher();

user.PasswordHash = passwordHasher.HashPassword(password);

db.SaveChanges();

4 Comments

Hi thanks, I was going to try your approach. I think the approach by 'wal' above is more direct. I didn't want to meddle with EF especially with the identity user models and tables.
@SKale At first I used the approach in the other answer, which is totally valid. The problem I have with this was that I use this from a management tool in WPF. By using that approach I had to have a list of dependencies to Owin, Identity, etc. Because I did not liked this, I took this approach as it will require only one reference to Microsoft.AspNet.Identity
Yours is a very valid approach and helpful in many cases I am sure. I did mark it ass a correct alternate answer. But I have not figured out how to directly interact through EF using Asp.Net.Identity. For example, suppose I want to simply update an email in the AspNetUsers table, how do you do that? Where are the models, I wish I could just scaffold those and be done with it.
I created an in between contract assembly where I located the models that came from the template. This contract is being used by Identity from the MVC assembly and from my management app. Not that hard to do. I got rid of the ApplicationDbContext and replaced this with a more or less default DbContext. The ApplicationUserManager will accept any DbContext. Is not needed to let this be a IdentityDbContext<TUser>
0

You have to get the user from the database and generate the code not by username :

public async Task<Unit> ResetPassword(string userName, string password)
    {
        if (!string.IsNullOrWhiteSpace(userName))
        {
            var returnUser = await _userManager.Users.Where(x => x.UserName == userName).FirstOrDefaultAsync();

            var code = await _userManager.GeneratePasswordResetTokenAsync(returnUser);

            if (returnUser != null)
                await _userManager.ResetPasswordAsync(returnUser, code, password);
        }

        return Unit.Value;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.