Skip to main content

System.InvalidOperationException: ID1073: A CryptographicException occurred when attempting to decrypt the cookie using the ProtectedData API (see inner exception for details).

Last week I spend a lot of time searching for a specific WIF issue we encountered.

The Facts

Let’s first describe the situation before I come to the error itself. We have a root ASP.NET MVC Website e.g. portal.sample.be/ and a list of subsites portal.sample.be/subsite1, portal.sample.be/subbsite2,…  Users always have to login through the root site before they can use any of the subsites. Login is handled through WIF and a range of STS instances(depending on the  authentication type). Once logged in on the root site, users have Single-Sign-On and can connect to any of the subsites without authenticating again.

The Issue

Last week we upgraded the root site to ASP.NET MVC 5, .NET 4.5 and the build-in System.IdentityModel and System.IdentityModel.Services. The sub sites are still using .NET 4.0, System.IdentityModel and Microsoft.IdentityModel. Authentication on the root site works as expected, but when we try to connect to any of the subsites, SSO fails and WIF returns the following exception:

System.InvalidOperationException: ID1073: A CryptographicException occurred when attempting to decrypt the cookie using the ProtectedData API (see inner exception for details). If you are using IIS 7.5, this could be due to the loadUserProfile setting on the Application Pool being set to false. ---> System.Security.Cryptography.CryptographicException: The data is invalid.

at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope)
at System.IdentityModel.ProtectedDataCookieTransform.Decode(Byte[] encoded)
--- End of inner exception stack trace ---
at System.IdentityModel.ProtectedDataCookieTransform.Decode(Byte[] encoded)
at System.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound)
at System.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)
at System.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver)
at System.IdentityModel.Services.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie)
at System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken)
at System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs)

If you search for this fault on the Internet, you find a small range of possible reasons and solutions:

  • The LoadUserProfile setting in IIS is set to false. This should be true to make DPAPI work.
  • Switch to MachineKey protection in WIF for .NET 4.5.
  • You are using an old cookie. Clear the browser cache.

We tried them all but none of them brought a solution. After a long quest, we finally figured it out:

The internal format of the cookie has changed between WIF version for .NET 4.0 and .NET 4.5. So we can no longer share the cookie between sites as we are running multiple versions of .NET (and WIF). As a workaround, we switched back to the old WIF version on .NET 4.5. This solved the issue for now…

Remark: We are planning to implement a better solution in the long run by letting each site go back to the STS and use it’s own cookies.

Popular posts from this blog

.NET 8–Keyed/Named Services

A feature that a lot of IoC container libraries support but that was missing in the default DI container provided by Microsoft is the support for Keyed or Named Services. This feature allows you to register the same type multiple times using different names, allowing you to resolve a specific instance based on the circumstances. Although there is some controversy if supporting this feature is a good idea or not, it certainly can be handy. To support this feature a new interface IKeyedServiceProvider got introduced in .NET 8 providing 2 new methods on our ServiceProvider instance: object? GetKeyedService(Type serviceType, object? serviceKey); object GetRequiredKeyedService(Type serviceType, object? serviceKey); To use it, we need to register our service using one of the new extension methods: Resolving the service can be done either through the FromKeyedServices attribute: or by injecting the IKeyedServiceProvider interface and calling the GetRequiredKeyedServic...

Azure DevOps/ GitHub emoji

I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.

Kubernetes–Limit your environmental impact

Reducing the carbon footprint and CO2 emission of our (cloud) workloads, is a responsibility of all of us. If you are running a Kubernetes cluster, have a look at Kube-Green . kube-green is a simple Kubernetes operator that automatically shuts down (some of) your pods when you don't need them. A single pod produces about 11 Kg CO2eq per year( here the calculation). Reason enough to give it a try! Installing kube-green in your cluster The easiest way to install the operator in your cluster is through kubectl. We first need to install a cert-manager: kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml Remark: Wait a minute before you continue as it can take some time before the cert-manager is up & running inside your cluster. Now we can install the kube-green operator: kubectl apply -f https://github.com/kube-green/kube-green/releases/latest/download/kube-green.yaml Now in the namespace where we want t...