Using the .NET WCF BasicHttpBinding to access a web service using both Client Certificates AND Windows Authentication.
If you're using the WCF BasicHttpBinding to access a web service you may wish to connect using Windows Authentication over HTTPS but also present a client certificate to add an extra layer of security (two factor authentication).
The problem is whilst you can add a client certificate it is ignored because settings the ClientCredentialType to Windows means that only Windows authentication is used.
BasicHttpBinding basicBinding = new
BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicBinding.Security.Transport.ClientCredentialType
= HttpClientCredentialType.Windows;
SchedulerAccessWebServiceSoapClient
server = new SchedulerAccessWebServiceSoapClient(binding,
remoteAddress);
server.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine,
StoreName.My, X509FindType.FindByThumbprint, "be4bca8c388af02ee1c50c3f5f74d6a34fe97daf");
When you try and access the web service when Require Client Certificates is enabled you see an error similar to this.
System.ServiceModel.Security.MessageSecurityException: The HTTP request was forbidden with client authentication scheme 'Negotiate'. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden.
The limitation here is not with WCF but with the BasicHttpBinding, these bindings are really just helpers that generate the underlying binding elements. By using a CustomBinding you can get the underlying HttpsTransportBindingElement generated by the BasicHttpBinding, and modify it setting RequireClientCertificate to true.
Both Windows Authentication and Client Certificate authentication is then used.
/// <summary>
/// Connects
to the remote web service using both Windows authentication and a client
certificate.
/// </summary>
private void ConnectWebService()
{
String url = "https://centrel-ws01/xiaautomation/webservice/scheduler/scheduleraccesswebservice.asmx";
EndpointAddress remoteAddress = new EndpointAddress(url);
BasicHttpBinding basicBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicBinding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Windows;
CustomBinding binding = new CustomBinding(basicBinding);
HttpsTransportBindingElement transportBindingElement =
binding.Elements.Find<HttpsTransportBindingElement>();
transportBindingElement.RequireClientCertificate = true;
SchedulerAccessWebServiceSoapClient server = new
SchedulerAccessWebServiceSoapClient(binding, remoteAddress);
server.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine,
StoreName.My, X509FindType.FindByThumbprint, "be4bca8c388af02ee1c50c3f5f74d6a34fe97daf");
String authenticatedUserName = server.GET_AuthenticatedUserName();
MessageBox.Show(authenticatedUserName);
}
Comments
Post a Comment