Consuming a WCF Service with an unmanaged C++ client with credential passing

After much hassle I eventually got this working. This post explains how I got it to work and will try and pull together several information sources I found during the investigation.

Service, Step 1 – Bindings and Security

To maximize the interoperability of the WCF service, whilst maintaining credential flow, the WCF service needs to be setup in a particular way. The most critical issue is choosing the correct bindings and security settings; I spent ages trying to get a basicHttpbinding with security mode “TransportWithMessageCredentials” to work. This turned out to be the wrong way to do it (in our scenario). The eventual security mode was “Transport” with the transport clientCredentialType set to “Windows”

<basicHttpBinding>
<binding name="basic">
 <security mode="Transport">
  <transport clientCredentialType="Windows" />
 </security>
</binding>
</basicHttpBinding>

This basically says that the security should be provided by the transport layer (SSL with http – https), with windows credentials being passed at the transport layer (http headers – I think). The next problem is getting the service hosted in IIS.

Service, Step 2 – IIS setup

The credentials in IIS must match the service’s binding configuration. In this case this means setting the security settings to disable anonymous access and enable Windows authentication. Note that the service must be hosted on a SSL site (see this post for how to set this up). Try to build and view the service

If you see an error message saying that the service requires anonymous access this probably means there is something wrong with your bindings. In my case this was due to the fact that I had a mex endpoint for the service (as it was automatically generated), but as this was not using the same bindingconfiguration it was causing problems later on as it demanded anonymous access (in IIS). It is important that all the endpoints for the service have compatible security settings.

If you see an error message saying that the service requires windows authentication this may be due to an error with IIS. (See this blog entry for a possible resolution – note that in my case due to a complex IIS setup the instructions weren’t quite right, basically make sure that for the <IISWebService> section that relates to your site, the line ‘NTAuthenticationProviders=”Negotiate,NTLM” ‘ is included.

By this point you should be able to view the service in your web browser and view the wsdl.

Service, Step 3 – Improving WSDL interoperability 

The default behaviour of WCF allows for wsdl documents and xsd schemas to be imported into the overall wsdl (using the wsdl=wsdl0, xsd=xsd0 syntax). Some client side proxy generation tools are unable to handle these imports. Therefore to improve the interoperability you can do the following:

Use a WSDLExportExtension to include XSD inline
WCF behaviours allow services to override how WSDLs are generated. A custom behaviour can remove all imported xsds and place them inline. Details can be found at http://www.winterdom.com/weblog/2006/10/03/InlineXSDInWSDLWithWCF.aspx

Make all WSDLs appear inline
It may also be possible to use a custom behaviour to inline and imported wsdls, however as far as I am aware no-one has created this. On the plus side as long as all contract types (data, fault, service) share the same xml namespace then no wsdls are imported anyway.

 

Client, Step 1 – Prepare the WSDL for consumption

Even with the improvements to WSDL interoperability the C++ proxy generation tool (sproxy) will fail with the current WSDL due to the security settings being included using ws-policy sections. To get around this, take a local copy of the wsdl by saving the wsdl from your web browser. Then remove any mentions to policy as detailed here 

Client, Step 2 – Generate a C++ proxy using sproxy 

Open a visual studio command prompt (note you should be able to do this from Visual Studio using “Add Web Reference” however in practice there seems to be some differences). Navigate to the location where you stored your modified wsdl, and type the following command:

>sproxy /wsdl wsdlfileLocation.wsdl

Client, Step 3 – Include the proxy in your C++ project

Simply take the contents of the file generated in the previous step and paste into a standard C++ header file.

Client, Step 4 – Make the call to the web service

The standard sproxy generated proxies use CSoapSocketClientT, to make the web service calls. However you can specify a different type (as long as it conforms to the ATL SOAP Client Archetype), this means that we can use CSoapWininetClient, this type has built in capabilities to using secured communication and so the client credentials will be automatically included.  As yet my client is a simple console app, and at the moment it crashes (I’m not a C++ expert!), it does, however, successully call the service and receives a response.

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(NULL);
	{
	CTestInterfaceT<CSoapWininetClient> cli;
	int te;
	HRESULT res= cli.MyOperation(&te);
	cli.Cleanup();
	}
	Uninitialize();
	return 0;
}

And there we have it ladies and gentlemen!  An unmanaged C++ client calling a WCF service with transport level security and authentication.

About Alex McMahon

I am a software developer, interested in .net, agile, alt.net. I've previously specialised with .net 3.0 technologies like WCF, whereas now I am trying to specialise in agile development and best practice and patterns. I am obsessed with looking at the latest technologies, tools, and methods, and trying them out. I am currently employed by Rockwell Collins in the UK.
This entry was posted in C++, development, interoperability, Security, unmanaged, wcf, wcf behaviors, web service. Bookmark the permalink.

5 Responses to Consuming a WCF Service with an unmanaged C++ client with credential passing

  1. Pingback: Unmanaged C++ client for WCF service. at blinnov’s blog

  2. krishnapg says:

    Excellent work. We need more like this 🙂

  3. Francisco Ortega says:

    Im trying to find the same thing but calling the WCF from a c++ 6.0. Has anyone found a way to acomplish this?

    I saw this on http://msdn.microsoft.com/en-us/library/bb735856.aspx#intgrwf_complus with VB6 but i neet it with c++

    Any ideas?

    Thanks

  4. rbfigueira says:

    Hi,
    Do you have any simple working sample ?
    Please share 😀

    Thanks

Leave a reply to Francisco Ortega Cancel reply