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

Popular posts from this blog

Windows Server 2016, 2019, 2022, Windows 10 and Windows 11: Date and time "Some settings are managed by your organization".

TFTPD32 or TFTPD64 reports Bind error 10013 An attempt was made to access a socket in a way forbidden by its access permissions.

Windows Server 2019 desktop icons such as My Computer, Windows cannot access the specified device, path, or file.