2

I'm trying to implement Https Client Authentication in my application but I am having trouble finding any documentation on how to do it.

Looking through the MSDN documents I came up with this

// Certificate file in DER format (.cer or .p7b)   
string CountriesFile = @"Assets\https-client.keystore.cer";
StorageFolder InstallationFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFile file = await InstallationFolder.GetFileAsync(CountriesFile);

// Read the file into a buffer
IBuffer buffer = await Windows.Storage.FileIO.ReadBufferAsync(file);

// Create the Certificate object
Certificate ClientCert = new Certificate(buffer);
HttpBaseProtocolFilter aHBPF = new HttpBaseProtocolFilter();
aHBPF.ClientCertificate = ClientCert;

// Create our http client and send the request.
HttpClient httpClient = new HttpClient(aHBPF);
HttpResponseMessage response = await httpClient.SendRequestAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).AsTask(cts.Token);

I put this code together looking at the docs for HttpClient, HttpBaseProtocolFilter and Certificate. Making the assumption that I should have the certificate in the required format and read the file into the Certificate class.

The above code doesn't work and throws this error

An exception of type 'System.ArgumentException' occurred in MyLib.DLL but was not handled in user code
WinRT information: The certificate specified is missing the required private key information.

I have tested my server set-up and it works with client auth through a browser, which leads me to two possible conclusions.

  1. The certificate file is in the wrong format (though I would have hoped the exception would get thrown when the Certificate class is constructed).
  2. This is not intended way to do it!

Any one know how it should be done?

Ne0
  • 2,688
  • 3
  • 35
  • 49
  • On the HRESULT 0x80072F7D, please take a look at [this question](http://stackoverflow.com/questions/37019697/tls-client-certificate-authentication-on-uwp-windows-store-app) and the solution. – IMS May 13 '16 at 12:42

1 Answers1

2

It would appear that you have to install the certificate at a User level before you can effectively use it for client authentication within a Windows Store App

// Needs to be a PKCS12 (p12/pfx) file
string certPath = @"Assets\https-client.keystore.p12";
StorageFile file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(certPath);
IBuffer buffer = await FileIO.ReadBufferAsync(file);
string certData = CryptographicBuffer.EncodeToBase64String(buffer);

// Will ask the user if they want this app to install the certificate if its not already installed.
await CertificateEnrollmentManager.UserCertificateEnrollmentManager.ImportPfxDataAsync(
     certData,
     "PASSWORD",
     ExportOption.NotExportable,
     KeyProtectionLevel.NoConsent,
     InstallOptions.None,
     "MyFriendlyName"); 

Now the certificate is installed, it will be available to us in the certificate store.

var certificate = await CertificateStores.FindAllAsync(new CertificateQuery() { FriendlyName = "MyFriendlyName" });
ClientCert = certificate.Single();

HttpBaseProtocolFilter aHBPF = new HttpBaseProtocolFilter();
aHBPF.ClientCertificate = ClientCert;

// Create our http client and send the request.
HttpClient httpClient = new HttpClient(aHBPF);
HttpResponseMessage response = await httpClient.SendRequestAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).AsTask(cts.Token);

I would prefer to be able to make the certificate available to only the application and will update this answer if I find a way of doing it.

Ne0
  • 2,688
  • 3
  • 35
  • 49
  • When I use this code, I get the message "Exception from HRESULT: 0x80072F7D" Do you know why this happens? – Kateryna Gridina Jan 22 '15 at 14:31
  • Same here. This thing is starting to drive me crazzy. – slash33 Apr 20 '15 at 08:58
  • Do you have no choice but to install the certificate? Can I do it all in code without going to the user store? – tofutim Jun 25 '15 at 21:35
  • 1
    My understanding is that [ImportPfxDataAsync](https://msdn.microsoft.com/en-us/library/windows/apps/dn298295.aspx) add the certificate for the app's use only and not for the user. But the doc's don't appear to be clear on this. – Ne0 Jun 29 '15 at 09:03
  • The error 0x80072f7d is WinHttp: 12157 ERROR_WINHTTP_SECURE_CHANNEL_ERROR. It simply means that the connection could not be established because the client certificate was not available (could not be used/trusted). – Tomas Karban May 09 '16 at 12:55