3

I got this exception with SignalR, deployed in Azure WebSites. It works fine in debug environment. It's SignalR 1.0.1 and I use .NET MVC and WebApi

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.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: 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.

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 
[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.]
Microsoft.Owin.Host.SystemWeb.<>c__DisplayClass1.<GetRethrowWithNoStackLossDelegate>b__0(Exception ex) +27
Microsoft.Owin.Host.SystemWeb.Utils.RethrowWithOriginalStack(Exception ex) +15
Microsoft.Owin.Host.SystemWeb.CallContextAsyncResult.End(IAsyncResult result) +47
Microsoft.Owin.Host.SystemWeb.OwinHttpHandler.EndProcessRequest(IAsyncResult result) +7
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9629708
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

Do you have any idea ? Thanks

Raph
  • 374
  • 1
  • 16
  • 2
    I'm guessing you're using a custom dependency resolver and you didn't register the right IProtectedData or you implemented Register when you shouldn't have. – davidfowl Mar 14 '13 at 04:41
  • 1
    I'm using Ninject, and didn't register IProtectedData. Should I ? How ? – Raph Mar 14 '13 at 08:50
  • Nevermind, I will go Azure Cloud, thanks – Raph Mar 14 '13 at 10:58
  • Sure? I'm not sure what "Azure Cloud" has to do with this issue. You're doing something wrong regardless. Did you override Register? If you did, don't do it and it'll likely work on azure websites. – davidfowl Mar 15 '13 at 03:19
  • I don't know how, but it's working with Azure cloud computing. I didn't override Register. – Raph Mar 15 '13 at 09:16
  • I know why it's working but doesn't mean your code is fixed. If you're happy with it as is then thats ok. – davidfowl Mar 15 '13 at 16:43

4 Answers4

5

For others coming to this page, I had the same issue but the solution was much simpler. As mentioned in comments above, the accepted answer is bad. Also mentioned is that SignalR defaults to use MachineKeyDataProtector for IProtectedData. MapHubs and MapConnection both call a function InitializeProtectedData which registers MachineKeyDataProtector with the dependency resolver.

My problem was that I was mapping my SignalR routes, and THEN configuring the dependency resolver

RouteTable.Routes.MapConnection<SomeEndpoint>("SomeEndpoint", "SomeEndpointUrl");
GlobalHost.DependencyResolver = 
                     new StructureMapDependencyResolver(ObjectFactory.Container);

So basically the IProtectedData resolver registration done by MapConnection -> InitializeProtectedData was getting blown away when I registered my custom resolver. Simple fix, set the resolver BEFORE mapping the connection.

GlobalHost.DependencyResolver = 
                     new StructureMapDependencyResolver(ObjectFactory.Container);
RouteTable.Routes.MapConnection<SomeEndpoint>("SomeEndpoint", "SomeEndpointUrl");
Simon Fox
  • 10,409
  • 7
  • 60
  • 81
2

This is the single post that allowed my to resolve this same issue using the following code. dfowlers mention of registering an instance of IProtectedData led me to search and find the definition here.

Note this issue was not encountered when using the Visual Studio development server, but when moving to live. I'm glad I found this post, as I have no idea how I would have been supposed to know to implement IProtectedData otherwise. Maybe there's something deeper in the documentation.

Whether or not this is 100% the correct solution I'm not sure, but this worked for me. I created a class implementing IProtectedData, and then registered that with Ninject.

Class:

using Microsoft.AspNet.SignalR.Infrastructure;

namespace Fwr.DataTeamUploader.Logic
{
    public class ProtectedData : IProtectedData
    {

        // Obviously this isn't doing much to protect the data,
        // assume custom encryption required here

        // To reiterate, no encryption is VERY^4 BAD, see comments.

        public string Protect(string data, string purpose)
        {
            return data;
        }

        public string Unprotect(string protectedValue, string purpose)
        {
            return protectedValue;
        }
    }
}

Ninject registration:

/// <summary>
/// Load your modules or register your services here
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
    ...

    kernel.Bind<IProtectedData>().To<ProtectedData>();

    ...
gbro3n
  • 6,729
  • 9
  • 59
  • 100
  • 1
    I wouldn't show code like this because when you remove encryption. That's VERY VERY VERY VERY BAD as now you're completely unprotected. I know you mention that you should have custom crypto here but even showing it with this code is just bad. The reason this issue is happening is because for some odd reason it's using the wrong data protection. It's supposed to use the machine key provider which the call to MapHubs pts in the dependency resolver. – davidfowl Apr 18 '13 at 21:26
  • 1
    Thanks dfowler. I understand that this means comms are unsecured as per notes. This post just demonstrates the work around in the simplest possible way. This bug showed up when moving from development using SignalR 1.0.1 on a Win 7 machine to Win Server 2008 R2 production server. With no other information as to source of issue, this was my only means of fixing it (with custom encryption). Can you suggest a fix that resolves issue a better way? I will edit the post accordingly. – gbro3n Apr 19 '13 at 07:47
  • I agree with @dfowler but I just had the same issue in DEV environment (Win 7 - VS 2010 - Unity IoC) and this is the only fix I've found so far. Any suggestion is welcome! – ab_732 Jun 24 '13 at 18:11
  • Your Unity IoC is likely the culprit. You're likely replacing the protected data registered when calling MapHubs with the default one by mistake. Calling MapHubs() registers a machine key based protected data implementation instead of the default one that will throw this exception on windows azure. If you can figure out why it's being replaced then you'll figure out the issue. – davidfowl Jun 25 '13 at 05:28
0

Now in this case, you can now use the extension method MapsHubs() from Microsoft.AspNet.SignalR.SystemWeb package.

MachineKeyProtectedData will be used instead of the default implementation.

pb2q
  • 58,613
  • 19
  • 146
  • 147
Ben
  • 26
  • 2
-1

I do not believe Azure Websites are able to communicate with certificates/crypto API. Similar issues occur when trying to call Azure Management API. The user context under which the Sites are running appears to not have enough permissions to do so.

Igorek
  • 15,716
  • 3
  • 54
  • 92