How to create password reset token without OWIN initialization?

Dec 3, 2014 at 6:02 PM
Edited Dec 3, 2014 at 6:05 PM
All,

I have an internal admin website where we need to add a feature to create a password reset token. Here is what we have done so far (but it doesn't work):
        var manager = new ARRTUserManager(new ARRTUserStore(new DB2(), HttpContext.Current));
        manager.SetApplicationIdentity(Convert.ToInt32(ConfigurationManager.AppSettings["AuthenticationApplicationID"]));
        IdentityUser idUser = manager.FindByEmail(user.Email);

        var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ARRTAuth");
        manager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<IdentityUser, long>(provider.Create("PR"));
        string s = manager.UserTokenProvider.GenerateAsync("ResetPassword", manager, idUser).Result;
Now when we create a password reset code, it generates one however it is not generated properly.

On the production website we have available to us an OWIN object that seems to have the DPAPI provider all initialized for us, and this code works just fine on it. However because our internal website doesn't use IDENTITY Framework, we of course have no reference to an IAppBuilder object or OWIN context information:
      var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
      IdentityUser idUser = manager.FindByEmail("joe@smith.com");

      string resetCode = manager.GeneratePasswordResetToken(idUser.Id);
Running the above code on the public facing website itself however works fine as long as you let the OWIN stuff create the OWIN object in a startup class like this:
     public void ConfigureAuth(IAppBuilder app)
    {
      app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); 
    }
However our internal admin we were hopping to initialize it as shown in the first code snippet, however the password reset codes that are generated are INCORRECT and do not work on the production website.

How to generate password reset tokens for a website that is using Identity Framework, but do it within a different internal application that is NOT using the identity framework?
Dec 3, 2014 at 8:43 PM
After a lot of reflection and google searching I finally figured out how this works with ASP .NET identity framework.

A good read is this: http://stackoverflow.com/questions/23455579/generating-reset-password-token-does-not-work-in-azure-website

Basically the Identity framework uses it's own implementation of a MachineKeyDataProtectionProvider that is located in Microsoft.Owin.Host.SystemWeb.DataProtection library.

I had to create my own implementation because those classes are marked internal. It basically is exactly the same as the Microsoft ones which is also shown in the stackoverflow article above.

Once I had that I could initialize my UserManager identity framework class with a UserTokenProvider the same way that the OWIN initialization routine does in Microsoft.Owin.Host.SystemWeb.
        var manager = new ARRTUserManager(new ARRTUserStore(new DB2(), HttpContext.Current));
        IdentityUser idUser = manager.FindByEmail(user.Email);
        var provider = new ABIILibrary.IdentityFramework.MachineKeyProtectionProvider();
        manager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<IdentityUser, long>(provider.Create("PR"));
The key thing here however is that the internal administrative site needs to have the same MachineKey in the web.config as the public facing website (same issues you normally see in webfarms). In addition the purpose "PR" in the above .Create("PR") statement needs to be the same purpose definition as the public facing website.

Now I can create reset codes in the internal admin site the same way as the public facing website can.

Hurray!

Talk about confusing!
Marked as answer by MattOl on 12/3/2014 at 12:43 PM