4

I'm using ASP.NET Identity 2 with Entity Framework 5 (because our Oracle data provider does not support EF6). For some reason the password verification by means of UserManager.PasswordHasher.VerifyHashedPassword keeps failing.

My UserStore class contains:

    public Task SetPasswordHashAsync(IccmUser user, string passwordHash)
    {
        IPasswordHasher hasher = new PasswordHasher();

        var t = Task.Run(() => {
            user.PasswordHash = hasher.HashPassword(passwordHash);
        });
        return t;
    }

The (obviously hashed) password is stored in the database. Thus, this code seems to work just fine.

My AccountController does the password verification like this:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Login(SignInModel model, string returnUrl)
    {
        if (ModelState.IsValid) {
            // This fails:
            //var user = await UserManager.FindAsync(model.UserName, model.Password);

            // Thus: do it step by step.
            PasswordVerificationResult result = PasswordVerificationResult.Failed;

            // Step 1: find user.
            IccmUser user = await UserManager.FindByNameAsync(model.UserName);
            if (user == null) {
                ModelState.AddModelError("", "Couldn't find the user.");
            } else {
                // Step 2: validate password
                result = UserManager.PasswordHasher.VerifyHashedPassword(user.PasswordHash, model.Password);
                if (result != PasswordVerificationResult.Success) {
                    ModelState.AddModelError("", "The password is not valid.");
                } else {
                    // Step 3: sign-in user.
                    await SignInAsync(user, model.RememberMe);
                    return Redirect(returnUrl);
                }
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

The VerifyHashedPassword() in step 2 always returns Failed. Both parameters (PasswordHash and Password) are passed in correctly.

Any pointers to what I'm missing are greatly appreciated.

Windowlicker
  • 498
  • 11
  • 18
  • OK, another look after a short break reveals: SetPasswordHashAsync() already receives the password as hashed from UserManager.CreateAsync(). Thus, I shouldn't hash it again. – Windowlicker Jul 23 '14 at 04:15

1 Answers1

2

The error is in the UserStore implementation. SetPasswordHashAsync() is not supposed to hash the password. Instead, it receives the hashed password from UserManager.CreateAsync(). Thus, the following change in UserStore does the trick:

    public Task SetPasswordHashAsync(IccmUser user, string passwordHash)
    {
        return Task.FromResult(user.PasswordHash = passwordHash);
    }

Sorry for the noise.

Windowlicker
  • 498
  • 11
  • 18