Search code examples
dapperclaims-based-identityintuit-partner-platformpassword-hash

When does Identity IdentityUser PasswordHash update?


The reason I'm asking this is because I'm trying to create an MVC app/WebApi service, with ExternalLogin Credentials, specifically Intuit external credentials, and allow the login process to set the current identity of the web app, once logged into Intuit via it's 3-legged OAuth process. I'm doing so with Dapper as a backend, rather than EntityFramework.

If you make a default new project of an ASP.Net Web Application for Web API, it creates an AccountController and that contains an account management call named GetInfo. In that function it checks the PasswordHash, prior to setting local login provider information (PasswordHash is a property of IdentityUser):

        if (user.PasswordHash != null)
        {
            logins.Add(new UserLoginInfoViewModel
            {
                LoginProvider = LocalLoginProvider,
                ProviderKey = user.UserName,
            });
        }

So, obviously, the logic to manage PasswordHash is already accounted for elsewhere. Where might that be? I'm guessing, in a typical setup with EntityFramework, this is handled somewhere in the bowels of the IdentityUser class, or even the UserManager class (UserStore?). I can't find that in source code.

In my implementation with Dapper, to mimic what happens in Microsoft.AspNet.Identity.EntityFramework;

  1. Where should the calculation, setting, and verification, of PasswordHash occur?
  2. When should the property be set?

Or - do I not worry about this as some arcane black-ops process sets it for the Object??


Solution

  • A password is not being set, check your database after you have logged in with an external provider.

    What happens is:

    1. User wants to login
    2. User clicks on button to login with Google/Facebook
    3. Google/Facebook sends back an External Token along with some other information, after logging in.
    4. This token contains information about the user, that your MVC application will use to authenticate the user. (User Claims, uses cookies)
    5. Your MVC app will check within the database if an account already exists. 6 If it does not exists, it prompts the user to fill in a email adress that will be stored in your database (doesn't have to be the same email as google/facebook email).

    The process where all the magic happens is within the Owin.Security

    The process of Authenticating is within the ExternalLogin, ExternalLoginCallback methods. Which comes with the default MVC template

       // POST: /Account/ExternalLogin
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult ExternalLogin(string provider, string returnUrl)
        {
            // Request a redirect to the external login provider
            return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
        }
    
        // GET: /Account/ExternalLoginCallback
        [AllowAnonymous]
        public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
            if (loginInfo == null)
            {
                return RedirectToAction("Login");
            }
    
            // Sign in the user with this external login provider if the user already has a login
            var user = await UserManager.FindAsync(loginInfo.Login);
            if (user != null)
            {
                await SignInAsync(user, isPersistent: false);
                return RedirectToLocal(returnUrl);
            }
            else
            {
                // If the user does not have an account, then prompt the user to create an account
                ViewBag.ReturnUrl = returnUrl;
                ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
                return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
            }
        }