1

When developing a claim-based authentication application, in order to make the application working when deployed to load balancing servers, I followed http://msdn.microsoft.com/en-us/library/ff803371.aspx to replace the default SecurityTokenHandler by using a RsaTokenTransform handler to encrypt the session cookies using a self-provided certificate:

X509Certificate2 serviceCertificate = new X509Certificate2(certificate, certificatePassword);
List<CookieTransform> sessionTransformers =
    new List<CookieTransform>
    (
            new CookieTransform[]
        {
            new DeflateCookieTransform(),
            new RsaEncryptionCookieTransform(serviceCertificate),
            new RsaSignatureCookieTransform(serviceCertificate)
        }
    );
SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransformers.AsReadOnly());

FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);

To make the application more flexible and portable, the certificate is pulled from a database and stored in a X509Certificate2 object at runtime.

This is working with one server hosting the application but once I switched to a server farm, every now and then I got the error:

ID1014: The signature is not valid. The data may have been tampered with

Also some javascript, css and font files failed to load because of the same issue.

Related questions but did not solve the issue:

WIF- ID1014: The signature is not valid. The data may have been tampered with

WIF: ID1014: The signature is not valid. The data may have been tampered with

Community
  • 1
  • 1
everfor
  • 141
  • 1
  • 10

1 Answers1

4

After searching on the Internet I found no explicit explanations or solutions to the issue; to save people time who might encounter the same problem as me, here's the explanation:

The cause of the problem is that by default, X509Certificate2 object only offers a temporary Privatekey Provider, which does not persist among different servers in the server farm. Once the request goes from the original server to another one, the Privatekey Provider becomes empty (as it does not persist) on that server and thus the exception is thrown because the signature validation requires the private keys of the certificate.

To solve the problem one just needs to make the Privatekey Provider persistent when creating an X509Certificate2 object:

X509Certificate2 serviceCertificate = new X509Certificate2(certificate, certificatePassword, X509KeyStorageFlags.MachineKeySet|X509KeyStorageFlags.PersistKeySet);
everfor
  • 141
  • 1
  • 10