I have created an ASP.NET Core 3.1 web application from VS 2022 using the default template and selected Microsoft Identity to use Azure AD authentication. The wizards generated the app registration in my Azure AD tenant, and everything looks good (reply URLs etc.)

When I run the newly generated web application from the debugger, I get prompted for my Azure AD credentials and then I'm redirected back to my application and get the following exception:

Exception: Unable to unprotect the message.State. Unknown location Exception: An error was encountered while handling the remote login. Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync() 

Note that I have not added or modified any code. It is 100% as generated by the VS2022 template.

3

4 Answers

  • This error "Exception: Unable to unprotect the message.State", usually occurs when you have multiple OIDC middleware. Please check and see if you need to set a unique callback path for each OIDC if you have multiple.
  • Name the authentication schemes for each OIDC provider like oidc-demo and oidc-master.
  • The state parameter is not being decrypted properly when it is returned maybe because one of your OIDC providers is trying to decrypt/unprotect the message state of the other one.
  • Try to add the data protection provider as per the github discussion.

Please check the below links for data protection:

Configure ASP.NET Core Data Protection | Microsoft Docs

c# - Azure AD Authentication in Kubernetes Unable to unprotect the message.State - Stack Overflow

  • Make sure redirectURI should be an action method in your own controller like below:

     
  • Check UnProtect method in OnMessageReceived to decrypt as discussed in this link.

For more in detail, please refer below link:

asp.net core - Error code 500 "Unable to unprotect the message.State" when redirecting to Client in IdentityServer4 - Stack Overflow.

3

I was having the same problem with the vanilla ASP.NET 6 template with Azure AD auth, except that everything worked fine locally, but I received the Unable to unprotect the message.State. error when I deployed it to our kubernetes cluster.

For me, the issue was that the application was deployed to more than one instance behind the load balancer, so that caused the issues. I came across this issue on GitHub, which pointed me to this article that describes the problem and solution.

Solution 1

The article recommended utilizing a centralize data store that can be shared by all running instances to hold the auth keys, and set it up with code similar to this.

services.AddDataProtection() .SetApplicationName("MyApp") .SetDefaultKeyLifetime(TimeSpan.FromDays(30)) .PersistKeysToAzureBlobStorage(new Uri(""), new DefaultAzureCredential()) .ProtectKeysWithAzureKeyVault(new Uri(""), new DefaultAzureCredential()); 

Solution 2

My web app didn't utilize a database and I didn't want to introduce one just for auth, so instead I configured our ingress to use cookie persistence. This means that when a request is made, the response contains a cookie that the client will store and include on future requests. The cookie tells the ingress which instance to direct the request to, ensuring that requests from a specific client always end up hitting the same instance.

This may not be ideal in all scenarios, as it can prevent the load balancer from performing equal distribution of requests across all instances. That tradeoff was fine in my scenario though, as it's not a high volume service, and this is the solution I ended up using.

Here's an example of the nginx ingress yaml annotations I added:

 ingress: enabled: true annotations: 128k cookie my-service-name sha1 "1800" 

You can configure a similar cookie affinity rule in other products, like F5 load balancers, Azure App Gateways, etc.

Solution 3

The last option is to host only a single instance of your service, in which case all auth callbacks will hit that single service. This isn't ideal though, as it means you can't scale your web app for high availability.


How this relates to the original poster's issue of getting this error on their localhost while debugging, I'm not certain. Perhaps they have more than once instance running on their local machine, or a reverse proxy, or interceptor (like Fiddler) running on their localhost that is causing the problem? Either way, I thought I'd share my solutions for others that stumble across this question when searching for the error message.

In my case, the issue was when I have more than one running instance of the application. The problem is that when the callback is triggered you don't know to which instance of the application you will be returned. The fix is to use data protection with distributed cache like Redis.

Please consider this as an extension to the answers provided above.
We experienced the same error due to the simultaneous generation of the data protection key by 2 app instances behind a load balancer when the existing data protection key was near expiration. 2 different keys were generated and used during the next 24 hours causing the app erroring

Here is more information related to such race conditions:
What is the strategy of data-protection key rotation with multiple pods?

Additionally, there are such open issues on GitHub devoted to this error:

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.