If you need to Authenticate your Azure Web App (ASP.NET MVC Application) against WCF Service with a specified Client Certificate (.p12 in my case) you will find out that it is not quite simple as it sounds. There are plenty of samples of how to do it in Internet, but non of them has really worked for me! Here is a short list of what I have tested and what have worked and not worked:
1. Using Certification Store
First you need to upload your Certificate into your Azure Web App, and get the Thumbprint of it.
After that it is supposed to work with following line of code:
var service = new WCFServiceClient();
service.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByThumbprint,
"TUMBPRINT");
This solution DID NOT WORK! It can not find any Certificate with than (or any) Thumbprint when running as Azure Web App. Also tried changing the StoreLocation to CurrentUser but it did not help.
2. Loading file from File System
Second idea was to load it from my File System, so I put my Certificate in App_Data and rewritten my code to:
var service = new WCFServiceClient();
service.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(
"FILENAME.p12",
"PASSWORD",
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
This solution ALSO DID NOT WORK! It could not find specified file on my File System. By putting the Certificate on root of my Project and not in App_Data also did not help.
3. Loading the Certificate from Resource as byte[]
So I was looking at all overrides of X509Certificate2() ctor and I found that it is possible to give a Certificate as a byte[]. So I created a simple Resource file and added my Certificate as Existing File:
So I rewritten my code so I can get a byte[] out of my Resource file and initialize my Service Client with that Certificate:
var service = new WCFServiceClient();
service.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(
(byte[])Properties.Resources.ResourceManager.GetObject("RESOURCE"),
"PASSWORD",
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
And this code actually WORKED! I was able to make a SSL/TLS Connection to my WCF Endpoint successfully!
One more thing you should not forget is of course to define your Bindings in Web.Config correctly so that your client knows that he needs to Authenticate himself to Service with Client Certificate. Put or make sure you have following definition under your <system.serviceModel> tags:
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_WCFService" maxBufferPoolSize="20971520" maxBufferSize="20971520" maxReceivedMessageSize="20971520">
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Hope I saved you few hours of frustration!
Posted
Aug 14 2015, 03:28 PM
by
Armin Kalajdzija