Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#, How can I add the certificate to the HttpClientHandler?

Tags:

c#

ssl

I need to send data to a web api which needs a certificate to authorize. But I've no clue how I can add the certificate to the handler in .Net 4.5. This is the code:

// Import the certificate
X509Certificate2Collection certificates = new X509Certificate2Collection();
certificates.Import(pathToCertificate, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;

using (var handler = new HttpClientHandler() { })
{
    using (var client = new HttpClient(handler))
    {
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));


        // Build the JSON
        string json = JsonConvert.SerializeObject(userData, Formatting.Indented);
        Console.WriteLine(json);

        var httpContent = new StringContent(json, Encoding.UTF8, "application/json");

        var processResult = await client.PostAsync(uriToServer, httpContent);
        var responseBody = processResult.Content.ReadAsStringAsync().Result;

        Console.WriteLine(responseBody);
        //return JsonConvert.DeserializeObject<string>(responseBody);
    }
}

I searched google and found a "HttpClientHandler.ClientCertificates.Add" but that is .Net Core and not 4.5.

Is this possible with HttpClient or do I have to use the HttpWebRequest class?

UPDATE:

Related on the given answer from "Peter Bons" (thanks again) and since the using is only try-finally I changed the code to this:

// Create an WebRequestHandler instance
var handler = new WebRequestHandler();

// Add the certificate
var certFile = Path.Combine(pathToWorkingDirectory, "SERVER.PFX");
handler.ClientCertificates.Add(new X509Certificate2(certFile, "password"));

var client = new HttpClient(handler);
try
{
    //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var httpContent = new StringContent(json, Encoding.UTF8, "application/json");

    //var processResult = await client.GetAsync("https://server/login");
    var processResult = await client.PostAsync("https://server/p/m", httpContent);
    var responseBody = processResult.Content.ReadAsStringAsync().Result;

    Console.WriteLine(responseBody);
}
catch (Exception e)
{
    Console.WriteLine($"ERROR: {e}");
}
finally
{
    client.Dispose();
}

Unfortunately the Server response with 403 forbidden... How can I check if the authorization is working with the certificate?

UPDATE 2:

It seems like the answer to this question lies in the debugging: enter image description here

I tested the password and with the wrong password for the certificate a exception happens. So I am not sure if the server is accepting the certificate but the server path is dead or the server is not accepting the certificate.

UPDATE 3:

Looking at the response object showing more information but not if the certificate caused the error. enter image description here

But there is a Exception inside the content? enter image description here

UPDATE 4:

Unfortunately, the server never received the certificate...

LAST UPDATE

The problem was the certificate I got from our sysadmin. Code works. Problem solved. :)

like image 241
user3772108 Avatar asked Oct 30 '17 16:10

user3772108


1 Answers

You should use the WebRequestHandler class like in this example:

var handler = new WebRequestHandler();

var certFile = Path.Combine(@"d:\temp\", "cert.pfx");
handler.ClientCertificates.Add(new X509Certificate2(certFile, "password"));

using (var client = new HttpClient(handler))
{
    ....
}

See also this link for more background information

like image 181
Peter Bons Avatar answered Nov 12 '22 21:11

Peter Bons