Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are all the things SetPasswordHashAsync must accomplish in the IPasswordStore in MVC 5?

I'm a little flummoxed by trying to implement the IPasswordStore in the new asp.net mvc 5. I want to use my own ORM.

Take this familiar code snippet from the scaffolded 'AccountController' that runs when the 'register' screen is used in the example project.

public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser() { UserName = model.UserName };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                await SignInAsync(user, isPersistent: false);
                return RedirectToAction("Index", "Home");
            }
            else
            {
                AddErrors(result);
            }
        }

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

the

  var result = await UserManager.CreateAysnc(user, model.Password)

line first calls the IPasswordStore function

  public Task SetPasswordHashAsync(TUser user, string passwordHash)

without having first called from IUserStore

   public Task CreateAsync(TUser user)

How do I set the password hash if the user isn't created in the db yet? Furthermore, we actually don't even know if we can create the proposed 'user' because we haven't checked to see if the username is taken yet using

   public Task<TUser> FindByNameAsync(string userNameIn)

which is called right afterwards.

Any ideas?

like image 348
Isaac Bolinger Avatar asked Nov 23 '13 11:11

Isaac Bolinger


2 Answers

You are right in noticing that you probably should not persist the password hash for the user before the user is created. You could save the password hash to a location that will be reverted if the user is not actually created anyway. The password should not be stored untill the user is created and stored, i.e. in CreateAsync(TUser user).

The IdentityUser in the EntityFramework implementation would be such a location, and it would enable you to store both user and password information in the CreateAsync method. I am not saying you should reference the Identity.EntityFramework assembly, just saying that a User object that has both User and PasswordHash info similar to the IdentityUser is one possible solution.

like image 198
Olav Nybø Avatar answered Sep 28 '22 06:09

Olav Nybø


Always set the password hash property of your user object in the IUserPasswordStore.SetPasswordHashAsync method body as the IUser interface doesn't define the property so UserManager can't set it. If you do this and then only update the user database record if the user exists you can add the password hash when you finally create your user in the IUserStore.CreateAsync method.

This principal also works for the IUserSecurityStampStore.SetSecurityStampAsync method.

like image 27
stevehipwell Avatar answered Sep 28 '22 06:09

stevehipwell