CryptographicException on password reset when running in Microsoft Azure Web-Sites


This is a long-running issue for me (and measuring from amount of traffic I get on this blog post a lot of other people)

When using DataProtectorTokenProvider for UserManager.UserTokenProvider compined with new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider for IDataProtector, it works fine when running locally or on IIS in my control.

Whenever I run this code in Azure Web-Site, I get CryptographicException
System.Security.Cryptography.CryptographicException: The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating.
Not exactly sure what is missing, but there are a number of hacks (see my blog link above, this post and this post ) going about on on the interwebs.

Can we please either fix this issue within Idenetity framework or provide an official guide how to avoid this exception.
Closed Oct 21, 2014 at 1:39 PM by bdorrans
Closed by request.


bdorrans wrote Oct 20, 2014 at 7:17 PM

DPAPI is only for local, non-farmed machines. All other scenarios need the machine key protector.

This is handled for you usually. What scenario are you trying that requires you to create your own protection provider?

trailmax wrote Oct 21, 2014 at 12:40 AM

Yes, indeed, the default template works in Azure - just re-tried it.

But I'm trying to do DI with Identity and inject all the dependencies into UserManager, and also inject UserManager.

Howver, default Identity template has static _ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) _ method. And data protector is extracted from IdentityFactoryOptions options that is provided by OWIN/Identity (not sure which one exactly).

So to avoid taking dependency on IdentityFactoryOptions options that is not available in a DI framework, I somehow need to obtain IDataProtector that works in cloud environment.

Any advice?

trailmax wrote Oct 21, 2014 at 1:13 AM

Playing with this a bit more, I think I have found somewhat optimal solution:

In Startup.Auth.cs save the reference to IDataProtectionProvider in static variable:

```public partial class Startup{ internal static IDataProtectionProvider DataProtectionProvider { get; private set; }
public void ConfigureAuth(IAppBuilder app)    {        DataProtectionProvider = app.GetDataProtectionProvider();        // other stuff.    }}```
Then in UserManager access this variable:

```public class UserManager : UserManager{ public UserManager() : base(new UserStore(new MyDbContext())) { var dataProtectionProvider = Startup.DataProtectionProvider; this.UserTokenProvider = new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity"));
    // do other configuration    }}```
But I'm not sure if there are any drawbacks to this solution. What about object lifescope management? can this IDataProtectionProvider be assigned like that and kept untouched for the rest of the application life?

bdorrans wrote Oct 21, 2014 at 2:08 AM

A static should do just fine, IDataProtector is intended to be a singleton anyway

OzBobWA wrote Oct 21, 2014 at 3:28 AM

Now that's a great interaction, thanks @bdorrans for your quick reply. @trailmax will you update with a new blog post on your static DPAPI solution?

trailmax wrote Oct 21, 2014 at 10:30 AM

Thanks Bdorrans, I guess the issue can be closed.

And OzBob, I've updated my blog-post already)