Generating reset password token does not work in Azure Website Generating reset password token does not work in Azure Website azure azure

Generating reset password token does not work in Azure Website


The DpapiDataProtectionProvider utilizes DPAPI which will not work properly in a web farm/cloud environment since encrypted data can only be decrypted by the machine that encypted it. What you need is a way to encrypt data such that it can be decrypted by any machine in your environment. Unfortunately, ASP.NET Identity 2.0 does not include any other implementation of IProtectionProvider other than DpapiDataProtectionProvider. However, it's not too difficult to roll your own.

One option is to utilize the MachineKey class as follows:

public class MachineKeyProtectionProvider : IDataProtectionProvider{    public IDataProtector Create(params string[] purposes)    {        return new MachineKeyDataProtector(purposes);    }}public class MachineKeyDataProtector : IDataProtector{    private readonly string[] _purposes;    public MachineKeyDataProtector(string[] purposes)    {        _purposes = purposes;    }    public byte[] Protect(byte[] userData)    {        return MachineKey.Protect(userData, _purposes);    }    public byte[] Unprotect(byte[] protectedData)    {        return MachineKey.Unprotect(protectedData, _purposes);    }}

In order to use this option, there are a couple of steps that you would need to follow.

Step 1

Modify your code to use the MachineKeyProtectionProvider.

using Microsoft.AspNet.Identity.Owin;// ...var provider = new MachineKeyProtectionProvider();UserManager.UserTokenProvider = new DataProtectorTokenProvider<User>(    provider.Create("ResetPasswordPurpose"));

Step 2

Synchronize the MachineKey value across all the machines in your web farm/cloud environment. This sounds scary, but it's the same step that we've performed countless times before in order to get ViewState validation to work properly in a web farm (it also uses DPAPI).


Consider using IAppBuilder.GetDataProtectionProvider() instead of declaring a new DpapiDataProtectionProvider.

Similar to you, I had introduced this issue by configuring my UserManager like this, from a code sample I found:

public class UserManager : UserManager<ApplicationUser>{    public UserManager() : base(new UserStore<ApplicationUser>(new MyDbContext()))    {        // this does not work on azure!!!        var provider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ASP.NET IDENTITY");        this.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("EmailConfirmation"))        {            TokenLifespan = TimeSpan.FromHours(24),        };    }}

The CodePlex issue linked to above actually references a blog post which has been updated with a simpler solution to the problem. It recommends saving a static reference to the IDataProtector...

public partial class Startup{    internal static IDataProtectionProvider DataProtectionProvider { get; private set; }    public void ConfigureAuth(IAppBuilder app)    {        DataProtectionProvider = app.GetDataProtectionProvider();        // other stuff.    }}

...and then referencing it from within the UserManager

public class UserManager : UserManager<ApplicationUser>{    public UserManager() : base(new UserStore<ApplicationUser>(new MyDbContext()))    {        var dataProtectionProvider = Startup.DataProtectionProvider;        this.UserTokenProvider =                 new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));        // do other configuration    }}

The answer from johnso also provides a good example of how to wire this up using Autofac.


I had the same issues except I was hosting on amazon ec2.
I was able to resolve it by going to the application pool in IIS and (under advanced settings after a right click) setting process model - load user profile = true.