Search code examples
c#sslasp.net-coresoapcertificate

.Net Core Connected Service with SSL Certificate


I am trying to make a request to a web service endpoint that utilizes an SSL certificate for communication. I have spent hours googling for an example but have come up with very little so far.

I did manage to get the connected service to scaffold by directly navigating to the wsdl and xsd file, saving them manually and pointing the WCF Web Service Reference Provider to the containing directory based on this solution. I also tried installing the certificate with the winhttpcertcfg.exe but could not get the tool to successfully open the channel to generate the client directly from the WSDL.

Now that I have the client generated, I am unable to figure out how to add the certificate correctly. This is the code that I have currently

 // Get the certificate
                var testCert = new X509Certificate2(System.IO.File.ReadAllBytes("C://SecureCert.PFX"), "##########");

                //Create instance of SOAP client
                HostedCollectionPaymentService.OnlineService_v2_2Client soapClient = new OnlineService_v2_2Client(new BasicHttpsBinding(BasicHttpsSecurityMode.Transport), new EndpointAddress("https://secure.service.endpoint.com/2.2/"));

                // Add the certificate to the client
                soapClient.ClientCredentials.ClientCertificate.Certificate = testCert;

                using (new OperationContextScope(soapClient.InnerChannel))
                {
                    try
                    {
                        var result = await soapClient.startOnlineCollectionAsync(new StartOnlineCollectionRequest
                        {
                            app_id = "12344",
                            tracking_id = "fdsa43531",
                            transaction_amount = 5.00m,
                            transaction_type = TransactionType.Sale
                        });

                        Console.WriteLine(result.startOnlineCollectionResponse.token);
                    }
                    catch (Exception ex)
                    {
                        var f = ex;
                        throw;
                    }
                }

When i try to connect, i recieve the response "Message = "Could not establish trust relationship for the SSL/TLS secure channel with authority 'secure.service.endpoint.com'".

I have verified that the certificate is valid and I am able to connect to the service using the SoapUI toolset.

I am assuming that I am either missing a configuration or attaching the SSL certificate incorrectly. If someone could provide a suggestion or point me to the appropriate documentation I would be highly appreciative.


Solution

  • Figured it out. I need this extra configuration line.

    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    

    Here is a sample for those asking where it was included. In my case it was for a payment gateway service.

    // Get the cert
    var myCertificate = await GetMyCertificate(); //X509Cert
    
    // Create a new binding to specify certificate security
    var binding = new BasicHttpsBinding()
    {
        Name = "basic_ssl_cert"
    };
    
    // Specify the credential type
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
    
    
    //Create instance of SOAP client
    QaPaymentService.PaymentOnlineService_v2_Client soapClient = new QaPaymentService.PaymentOnlineService_v2_Client(binding, new EndpointAddress(onlinePaymentServiceEndpoint));
    
    // Add the certificate to the client
    soapClient.ClientCredentials.ClientCertificate.Certificate = myCertificate;
    
    
    using (new OperationContextScope(soapClient.InnerChannel))
    {
        try
        {
            var result = soapClient.completeOnlineCollectionAsync(new QaPaymentService.CompleteOnlineCollectionRequest
            {
                app_id = appId,
                token = token           
            }).GetAwaiter().GetResult();
    
            return (result.completeOnlineCollectionResponse.tracking_id);
        }
        catch (FaultException<QaPaymentService.PaymentServiceFault> ex)
        {
            // Extract the actuall error from the service fault
            throw new myServiceException(ex.Detail.return_detail, ex)
            {
                ErrorDetail = ex.Detail.return_detail,
                ErrorCode = ex.Detail.return_code
            };                       
        }
        catch (Exception ex)
        {
            logger.LogError($"Error completing transaction from QA my service: {ex.Message}", ex);
            throw ex;
        }
    }