Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[.NET 9.0 Regression] "Credentials supplied to the package were not recognized" when using certificates with wcf client #110067

Closed
julienGrd opened this issue Nov 21, 2024 · 5 comments

Comments

@julienGrd
Copy link

Description

Hello guys, i have a piece of code in my app which call a soap service using wcf client and certificate authentification.

This code work fine in .net8.0, but after upgrading to .net9.0 it stopped working and finish with this exception "Credentials supplied to the package were not recognized".

I was wondering which change made in the framework can explain that.

this is the part where i configure the service

  private void ManageEndpoint<T>(ClientBase<T> pClient) where T: class
  {
      pClient.Endpoint.Address = new EndpointAddress(_urlService);
      ServicePointManager.Expect100Continue = true;
      ServicePointManager.DefaultConnectionLimit = 9999;
      ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
      try
      {
         X509Certificate2 lAuthCertificate = new X509Certificate2(this._certif.CertifContent, this._certif.Password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);



          if (lAuthCertificate != null && pClient.Endpoint.Address.Uri.AbsoluteUri.StartsWith("https"))
          {

              //Ajout du certificat d’authentification aux crédentials pour etablir la connexion TLS
              if (pClient.ClientCredentials != null) pClient.ClientCredentials.ClientCertificate.Certificate = lAuthCertificate;

              System.Net.ServicePointManager.ServerCertificateValidationCallback += CertificateValidationCallBack;

              CheckCertificates();
          }
      }
      catch (Exception ex)
      {
          throw new Exception("Certificat INS invalide : " + ex.Message);
      }
  }


  private bool CertificateValidationCallBack(
                                                  object sender,
                                                  System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                                                  System.Security.Cryptography.X509Certificates.X509Chain chain,
                                                  System.Net.Security.SslPolicyErrors sslPolicyErrors)
  {
     return certificate.Subject.Contains("services-ps-tlsm.ameli.fr");
  }

Interesting things : since .net 9.0, all call to ServicePointManager are flag obsolete. But i don't know it the error can come frome here. The "new X509Certificate2" is also obsolete but if i change for "X509CertificateLoader.LoadPkcs12" i still have same error.

This error is really annoying for me, it would be really a pain to come back in .net 8.0 as i already upgraded many client.

Unfortunately i can't give a repro project as there is very sensitives informations, especially the certificate used for connexion (but if its really necessary, i will check that).

Do you have some tips on how i can debug that or if you know which changes can explain that ?

This issue is high priority for me.

thanks !

Reproduction Steps

calling wcf service with client certificate authentication

Expected behavior

Have the same behavior wetween .net8.0 and .net9.0

Actual behavior

the code throw exception in .net9.0

Regression?

yes, was working in .net8.0

Known Workarounds

no workaround for now

Configuration

.net9, win-x64

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Nov 21, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Nov 21, 2024
@vcsjones vcsjones added area-System.Net.Security and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Nov 22, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

@wfurt
Copy link
Member

wfurt commented Nov 22, 2024

this looks like dup of #109050. It seems like the something changed in certificate loading.
In general, I think this is sign that schannel cannot access the keys.

@julienGrd
Copy link
Author

this looks like dup of #109050. It seems like the something changed in certificate loading. In general, I think this is sign that schannel cannot access the keys.

I just solved my problem by removed the flag when i imported the certificate (i honestly don't know why i put these flags on the original code, but removing them seem make the job

=> code working in .net 8.0

X509Certificate2 lAuthCertificate = new X509Certificate2(this._certif.CertifContent, this._certif.Password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

=> code working in .net 9.0

X509Certificate2 lAuthCertificate = new X509Certificate2(this._certif.CertifContent);

but there is definitivly change in .net9 also in ServicePointManager
In .net 8 this event was fire System.Net.ServicePointManager.ServerCertificateValidationCallback, it's not in .net9.0

This is my final code which works in .net9, without warning and with tlsoption and callback

 private void ManageEndpoint<T>(ClientBase<T> pClient) where T: class
 {
     //porté par CustomHttpClientHander désormais
     //ServicePointManager.Expect100Continue = true;
     //ServicePointManager.DefaultConnectionLimit = 9999;
     ////plante si laisse SSL3
     //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;// | SecurityProtocolType.Ssl3;
     try
     {
         //on charge le certif
         X509Certificate2 lAuthCertificate = null;
         if (IsCps)
         {
             Pkcs11 lPkcs11 = new Pkcs11();
             lAuthCertificate = lPkcs11.authentificationCertificate;
             //SignatureCertificate = pkcs11.signatureCertificate;
         }
         else
         {
             //ne pas mettre de X509KeyStorageFlags, depuis .net 9 ca fait planté l'appel avec "Les informations d’identification fournies au package n’ont pas été reconnues"
             lAuthCertificate = X509CertificateLoader.LoadPkcs12(this._certif.CertifContent, this._certif.Password);
         }

         pClient.Endpoint.Address = new EndpointAddress(_urlService);
         var httpMessageHandler = new CustomHttpClientHander(IsCps, lAuthCertificate);
         pClient.Endpoint.EndpointBehaviors.Add(new CustomEndpointBehavior(httpMessageHandler));

         if (lAuthCertificate != null && pClient.Endpoint.Address.Uri.AbsoluteUri.StartsWith("https"))
         { // protocole TLS

             //Ajout du certificat d’authentification aux crédentials pour etablir la connexion TLS
             if (pClient.ClientCredentials != null) 
                 pClient.ClientCredentials.ClientCertificate.Certificate = lAuthCertificate;

             //porté par CustomHttpClientHander
             //System.Net.ServicePointManager.ServerCertificateValidationCallback += CertificateValidationCallBack;

             CheckCertificates();
         }
     }
     catch (Exception ex)
     {
         throw new Exception("Certificat INS invalide : " + ex.Message);
     }
 }

 public class CustomEndpointBehavior : IEndpointBehavior
 {
     private readonly Func<HttpMessageHandler> _httpHandler;

     public CustomEndpointBehavior(CustomHttpClientHander factory)
     {
         _httpHandler = () => factory.CreateHandler();
     }

     public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
     {
         bindingParameters.Add(new Func<HttpClientHandler, HttpMessageHandler>(handler => _httpHandler()));
     }

     public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
     public void Validate(ServiceEndpoint endpoint) { }
 }

 public class CustomHttpClientHander(bool IsCps, X509Certificate2 pAuthCertificate)
 {
     public HttpClientHandler CreateHandler()
     {

         var lHandler = new HttpClientHandler
         {
             ServerCertificateCustomValidationCallback = (HttpRequestMessage hrqMessage,
                 X509Certificate2 cert, X509Chain chain, SslPolicyErrors sslPolicyErrors) =>
             {
                 if (!IsCps)
                     return cert.Subject.Contains("services-ps-tlsm.ameli.fr");
                 else
                     return cert.Subject.Contains("services-ps.ameli.fr");
             },
             MaxConnectionsPerServer = 9999,
             SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls13
         };

         lHandler.ClientCertificates.Add(pAuthCertificate);

         return lHandler;
     }
 }

@wfurt
Copy link
Member

wfurt commented Nov 22, 2024

For a while the ServicePointManager was only applicable if you use HttpWebRequest but normally ignored by HttpClient. It is certainly possible that WCF has some layer on top of it. If you can reproduce behavior difference without WCF you can open separate issue in this repo. AFAIK obsoletion was really meant only for visibility. (way too many customers drag old properties that do nothing on .NET (Core))

@julienGrd
Copy link
Author

Yeah i don't know exactly neither but there is definitively a strange behavior with the wcf client.

anyway my problem is solved, and i get rid of call at the service point manager so everything is good on my side,,

thanks for your help !

@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Nov 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants