1

When sending a POST request from a HttpClient in ASP.NET Core application I am getting this exception:

System.ApplicationException: Error executing project task action 'WorkflowManager.Business.Logic.IStudio.Logic.TaskActions.XIS2SimulationTaskAction' for task 'WorkflowManager.Data.EF.Models.Project.ProjTask'. See InnerException for details. ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception. ---> System.ComponentModel.Win32Exception: The credentials supplied to the package were not recognized
   at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface secModule, String package, CredentialUse intent, SCHANNEL_CRED scc)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCHANNEL_CRED secureCredential)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(X509Certificate certificate, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer)
   at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)
   at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
   at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.BeginAuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken, AsyncCallback asyncCallback, Object asyncState)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_0(SslClientAuthenticationOptions arg1, CancellationToken arg2, AsyncCallback callback, Object state)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl[TArg1,TArg2](Func`5 beginMethod, Func`2 endFunction, Action`1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
   at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
   at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state)
   at System.Net.Security.SslStream.AuthenticateAsClientAsync(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---

I googled for a solution but nothing worked for me. Note that I am not loading the certificate from Local Machine/Current User storage, but directly from a PFX file.

I got the certificate in this way: I created a CSR certificate and a KEY private key using OpenSSL. Then I created a CSR request for this certificate. I sent the CSR to the appropriate department I want to communicate with to sign the certificate and got signed PEM file. Using OpenSSL I "merged" the PEM and KEY to a PFX file and defined a password.

Another strange thing is, as I created a minimal .NET Core console application like this:

 var url = "https://someurl:7443";
 HttpClientHandler ch = new HttpClientHandler();
 var certificate = new X509Certificate2("certificate.pfx", "password", X509KeyStorageFlags.DefaultKeySet);
 ch.ClientCertificates.Add(certificate);
 HttpClient client = new HttpClient(ch);
 var content = ..content..
 var response = client.PostAsync(url, content).Result;

This call with the same certificate works well. In the system I also use the HttpClient provided by IHttpClientFactory (typed factory, the certificate is bound to underlying handler).

The user account under the app runs in IIS has access to the PFX file.

On some different environment works everything fine so I think it is not issue of the code itself but its somehow related to some setting of certificates or IIS, but I dont have any idea to what.

Jan Drozen
  • 894
  • 2
  • 12
  • 28
  • this issue happens when either you did not store the private key with the certificate, or, the Windows service does not have access to the private key.iis users does not have enough permission to access all the things you need to assign the permission for the iis users. or you could change the iis application pool identity to the local system or custom user who has enough permission. – Jalpa Panchal Nov 01 '19 at 07:55
  • I read this solution, but I think it is not that case. As I wrote I use the PFX file directly using the X509Certificate2(file path,password) constructor. And the user on whose behalf the app in IIS runs has full control of the PFX file granted. Also tried to change from the service account to a local user account that definitely has access to the certificate file (the same used for the simple app test) but without any change. – Jan Drozen Nov 01 '19 at 08:28
  • could you share your web.config file? you could try to sue the process monitor to trace what exactly path it is using when ASP.NET core on IIS is trying to retrieve the client certificate.you can download process monitor from this link:https://learn.microsoft.com/en-us/sysinternals/downloads/procmon – Jalpa Panchal Nov 15 '19 at 09:12
  • 1
    [This thread](https://stackoverflow.com/questions/53334142/net-core-x509certificate2-usage-under-windows-iis-docker-linux) explores the same problem which has something to do with the way the imported certificate's private key is stored. I've fixed my issue(very similar to yours) by using `X509KeyStorageFlags.MachineKeySet`. – Angel Yordanov Aug 18 '21 at 05:27

0 Answers0