5

I have really strange problem with ASP.NET Identity and EntityFramework. I have a login form, from which I receive username and password. Then I check if the user exist in the database. After that I call the UserManager's method VerifyHashedPassword to verify that the user password from database and that from the form are the same. Everything is OK, but for some of the users in the database, the method give me result that the given password and the hashed password are not the same (but they actually are). I just can't figure out why for some of the users password verification fails.

Here's my code.

public async Task<User> FindUserAsync(string userName, string password)
    {
        User user;

        if (password != null)
        {
            user = await _userManager.FindByNameAsync(userName);

            if (user == null)
            {
                user = await _userManager.FindByEmailAsync(userName);
            }

            var result = _userManager.PasswordHasher.VerifyHashedPassword(user.PasswordHash, password);

            if (!(result == PasswordVerificationResult.Success))
            {
                return null;
            }
        }            

        return user;
    }
Zedx
  • 128
  • 1
  • 7
  • I assume you are using System.Web.Helpers Crypto.VerifyHashPassword... Check that user.PasswordHash is an RFC 2898 hash value as a base-64-encoded string. Also read http://stackoverflow.com/questions/20621950/asp-net-identity-default-password-hasher-how-does-it-work-and-is-it-secure It seems that the Verify is not the issue here. – Paul Zahra Oct 20 '15 at 11:21
  • I guess the leading question here is, how are you hashing the password? PasswordHasher() ? – Paul Zahra Oct 20 '15 at 11:29
  • I hash the password this way: _userManager.PasswordHasher.HashPassword(password); – Zedx Oct 20 '15 at 11:55
  • Or more precisely I call Identity's UserManager which uses IPasswordHasher interface and its implementation. – Zedx Oct 20 '15 at 11:57

2 Answers2

2

Well, the problem was on my side.

The problem came when some user decide to change their password. If user change their password, I first delete the password and then I add the new password to the database. Which was very dumb, because the transaction to the database with which I delete the password is committed successfully, but the transaction (for some reason) with which I add the new password was never done successfully.

Actually I used these two methods when a password is changed:

        await _userManager.RemovePasswordAsync(appUser.Id);
        await _userManager.AddPasswordAsync(appUser.Id, fbUser.Password);

Now I do that manually:

        String hashedNewPassword = _userManager.PasswordHasher.HashPassword(fbUser.Password);

        if (hashedNewPassword != null)
        {
            appUser.PasswordHash = hashedNewPassword;
            _context.Entry(appUser).State = EntityState.Modified;
            await _context.SaveChangesAsync();
        }  

And this works for me.

Zedx
  • 128
  • 1
  • 7
0

You can do this using the UserManager as long as you are able to do it async, the non-async extension method was broken for me at least, sending a null to the hashedPassword argument in the PasswordHasher. To do it async:

await _userManager.ChangePasswordAsync(userId, oldPassword, newPassword);
DatBear
  • 139
  • 1
  • 2
  • 8