27

I'm using WIF (.net 4.5), and Azure Active directory for authentication. The website will sit on Azure.

Everything works as expected locally, however when I put it onto azure I get the error:

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.

I understand this is because the apps can't use DAPI, so I need to switch to protecting my app with the MAC.

Locally I added this to my webconfig:-

 <securityTokenHandlers>
    <remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </securityTokenHandlers>

as recommended in the documentation, and I added a static machine key, but I can't find any advice around the key length - so I have assumed 256.

This configuration however just gives this error:

[CryptographicException: Error occurred during a cryptographic operation.] System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.HomogenizeErrors(Func`2 func, Byte[] input) +115 System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.Unprotect(Byte[] protectedData) +59 System.Web.Security.MachineKey.Unprotect(ICryptoServiceProvider cryptoServiceProvider, Byte[] protectedData, String[] purposes) +62 System.Web.Security.MachineKey.Unprotect(Byte[] protectedData, String[] purposes) +122 System.IdentityModel.Services.MachineKeyTransform.Decode(Byte[] encoded) +161 System.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound) +123 System.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver) +575 System.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver) +76 System.IdentityModel.Services.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) +833 System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +186 System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +210 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

I removed the machinekey section incase I hadn't specified a correctly formatted key, but the error doesn't go away.

What a fight WIF has been!

Ross Dargan
  • 5,876
  • 4
  • 40
  • 53
  • To fix my problem I added that to the web.config and generated a machine key with this site http://aspnetresources.com/tools/machineKey – Andrei Dvoynos Feb 05 '14 at 15:22

5 Answers5

49

If you don't specify machineKey in configuration, Azure adds one. But if you create new version of your application and deploy it to Azure using VIP switching, Azure generates a new machine Key for the deployment in Staging (assuming your first deployment was to Production). (VIP switching is nice mechanism for deploying new version and then switching virtual IP addresses between Production and Staging).

So basically one solution is letting Azure to generate the key but after VIP switch you have the problem back. To avoid it you can catch the CryptographicException in Global.asax in Application_Error handler, something like this:

// Be sure to reference System.IdentityModel.Services
// and include using System.IdentityModel.Services; 
// at the start of your class
protected void Application_Error(object sender, EventArgs e)
{
    var error = Server.GetLastError();
    var cryptoEx = error as CryptographicException;
    if (cryptoEx != null)
    {
        FederatedAuthentication.WSFederationAuthenticationModule.SignOut();
        Server.ClearError();
    }
}

The SignOut() method causes the cookie is removed.

Edit: updated info on generating machineKey as noted by @anjdreas.

Another solution is to generate the machineKey, you can use IIS Manager to do it, see Easiest way to generate MachineKey for details. If you put the same key into all your web appliactions within Azure Web Role, the Azure deployment process will not replace it.

Irwin
  • 12,551
  • 11
  • 67
  • 97
eXavier
  • 4,821
  • 4
  • 35
  • 57
  • 3
    If you don't want to use a 3rd party site, you can also use IIS Manager to generate the keys for you. http://blogs.msdn.com/b/amb/archive/2012/07/31/easiest-way-to-generate-machinekey.aspx – angularsen May 12 '14 at 21:23
  • aspnetresources.com appears to be a parked domain now. You should rewrite the last paragraph with anjdreas's link – bmm6o Aug 13 '15 at 18:38
  • The FederatedAuthentication in FederatedAuthentication.WSFederationAuthenticationModule is saying the name in 'FederatedAuthentication.WSFederationAuthenticationModule' does not exist in the current context and can't find what using i need to add. Using .net 4.6 – JQuery Jan 07 '16 at 13:16
  • 1
    @JQuery Assembly System.IdentityModel.Services, namespace: System.IdentityModel.Services. See [msdn](https://msdn.microsoft.com/en-us/library/system.identitymodel.services.wsfederationauthenticationmodule(v=vs.110).aspx) – eXavier Jan 07 '16 at 13:23
  • Thanks, I can add using System.IdentityModel to the global.asx but when i try adding Services i get The type or namespace name 'Services' does not exist in the namespace 'System.IdentityModel' (are you missing an assembly reference?) Using directive is unnecessary. – JQuery Jan 07 '16 at 13:46
  • trying this in relation to an error i am getting if possible see - http://stackoverflow.com/questions/34650138/error-occurred-during-a-cryptographic-operation-in-debug – JQuery Jan 07 '16 at 13:47
  • I am using the `SessionAuthenticationModule` rather than `WSFederationAuthenticationModule` for managing cookies, so I had to use `FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie()` instead of `SignOut()`. If using both [this SO answer](http://stackoverflow.com/a/13398903/4289902) may be useful... – Jono Job Jun 22 '16 at 23:51
4

The machine key shouldn't be there: Windows Azure generates one for you and makes sure it is identical on every instance in your role.

About the error you're seeing: can you try clearing cookies?

maartenba
  • 3,344
  • 18
  • 31
2

Simply clearing the cookies solved the whole problem for me in this case.

GGleGrand
  • 1,565
  • 1
  • 20
  • 45
  • Clearing the cookies worked for us too but this solution is not optimal as users will still see the error and need instructions for how to clear their cookies. Still, this is a solution so thanks. – spadelives Dec 08 '14 at 14:21
0

If you are using forms auth. you can signout when you catch the exception and allow your users to login and create a valid cookie

catch (CryptographicException cex)
{
    FormsAuthentication.SignOut();
}
Ozan BAYRAM
  • 2,780
  • 1
  • 28
  • 35
  • 1
    We had a problem with the solutions sign the user out automatically. Removing the cookie using this technique doesn't solve the problem and, when the cookies were cleared, the user was repeatedly signed out. We tried explicitly set the machinekey in the application's web.config file like this: ... We generated the encryption key using IIS7. We are still getting the error. – spadelives Dec 08 '14 at 14:02
-2

Asking all the users to clear all cookies wasn't really an option for me. On this site and also in the book "Programming Windows Identity Federation" I found a better solution (for me, anyways). If you're already uploading an SSL certificate to Azure, you can use that certificate to also encrypt your cookie on all Azure instances, and you won't need to worry about new machine keys, IIS user profiles, etc.

Inder Kumar Rathore
  • 39,458
  • 17
  • 135
  • 184
Greg Thatcher
  • 1,303
  • 20
  • 29