Archive for the ‘wcf’ Category

Username message credentials over streamed binding

A little while ago I added username authentication to some WCF services we have. This used message level authentication to hold the username and password, which required an x509 certificate to be used to secure the transport (as we’re sending passwords over it). One flaw was that message level security does not work with streamed bindings (as the message security, which comes before the message hits the service,  depends on the message body, so if it’s streamed you can’t establish security until the stream has finished). So a couple of our services require streamed bindings as they involve sending massive attachments to the WCF service (forget for the moment the dubiousness of sending massive attachments to a WCF service). This caveat was decided to be acceptable as all the other services were secured.

More recently it has become apparent that these streamed binding services also require security… oh dear! So it actually turns out it’s not that difficult, but oddly enough I couldn’t really find any directly related material on the interweb detailing this solution, so here it is.

For any streamed binding that needs to be secured using username message credentials set the security mode to mixed mode (TransportWithMessageCredential), the transport security to certificate and the message credential to username:

binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;                binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

This is a slightly different configuration than username based message security, and the caveat about streamed bindings does not apply. I think the difference is that instead of all security being taken care of at the message level only the credential passing is at the message level, other aspects of security are taken care of at the transport level. Therefore you no longer need the whole message body to establish security as this is taken care of at the transport layer. The disadvantage of using this security mode is that the transport is now essential for establishing security, so over multiple-hop connections the security wont work (I’m guessing). Therefore for non-streamed connections we’re going to stick to message security, degrading to mixed-mode security for streamed bindings.

Why does WCF security have to be so complicated? and how come I keep on getting lumbered with it? ;)

How to add custom policy assertions to a WCF service without using a custom binding

Recently I have been trying to work with the ws policy standard to add information to our service WSDLs. WCF has an extension point for doing just that, you can read a really good example of this WCF extension here. One limitation of this method is that you must use a binding of type ‘custom’.

It is worth mentioning at this point there is a really confusing issue with WCF bindings in that there is a pre-defined binding called ‘customBinding’ that gives you control over all the binding elements that make up a WCF binding. This allows you to completely tailor the binding at configuration time. You can also create your own binding type (in code) and allow this to be used at configuration time (the method explained in this post).

So what is the problem with using a ‘customBinding’? – Well we also require our services to use 2 possible bindings either basicHttpBinding or WSHttpBinding. We could create a ‘customBinding’ that mimics basic (or ws respectively) with the addition of a ‘PolicyExporter’ Binding element. However without digging down into the details of these 2 bindings how do we know what settings to use for the ‘customBinding’. This would also lead to even more complicated web.config files. We could also easily break the service at configuration time by changing part of the customBinding.

So what do we do? – Create 2 new bindings in code, each of which derives from either basicHttpBinding or WsHttpBinding, as well as adding a ‘PolicyExporter’ binding element (or any other custom binding elements we want). We then create some other classes that allow this binding to be used at configuration time. It is possible to manually create these classes, but there is also a tool that creates these classes based on a binding (saving time etc).

Step 1 – Create the binding
In a class library that can be referenced from the web.config (we have a dll for all our WCF extensions). Define a class that inherits from the binding, and overrides ‘CreateBindingElements’ like so:

 public class CustomBasicBinding:BasicHttpBinding
{
    public CustomBasicBinding():base()
    {
	//you can even define standard binding settings here!
        base.Security.Mode = BasicHttpSecurityMode.Transport;
	base.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
    }

    public override BindingElementCollection CreateBindingElements()
    {
        BindingElementCollection bindingEls = base.CreateBindingElements();
	//note that PolicyExporterBindingElement is a custom type defined elsewhere
        bindingEls.Insert(0,new PolicyExporterBindingElement(new GetPoliciesFromConfig()));
        return bindingEls;
    }
}

Step  2 – Use the tool to generate the other classes

The WCF samples download includes a useful tool to create these other classes. Download the samples, locate the source for the tool (TechnologySamples\Tools\ConfigurationCodeGenerator\CS), build the .exe, copy the exe to wherever the .dll for your custom binding is, use a command line and run the tool:

ConfigurationCodeGenerator.exe /sb:CustomBasicBinding /dll:<dll filename>

Step 3 – Copy generated code

navigate to the location of the dll, there should be one file  ‘CodeToAddTo<BindingName>‘  copy the contents of this file into your binding code. Copy the remaining generated files to your project location.

Step 4 – Use the new binding for your service

Modify the web.config for your service (either manually or using the WCF configuration tool). Add a ‘binding extension’, using the WCF config tool you can use a wizard to locate the dll and find the binding type (if you can’t see it in the dialog you’ve done something wrong!). Choose a name for the binding (used elsewhere in the config).

For any service endpoint that should use this binding, choose your new binding type as the binding for the service. If necessary you should also be able to create a BindingConfiguration (thanks to the generated code).

<extensions>
	<bindingExtensions>
		<add name="CustomBasic" type="Namespace.CustomBasicBindingCollectionElement, namespace, Version=1.0.0.1, Culture=neutral, PublicKeyToken='KEY'" />
	</bindingExtensions>
</extensions>
...
...
<services>
	<service code cut for clarity>
		<endpoint
			binding="CustomBasicBinding"
			...
		>
	</service>
</services>

An idea for exposing additional data and fault contracts for a WCF service through behaviours

Although I am not working on this at the moment I’ve just stumbled across something that I thought I should capture as a potential solution for an existing problem.

The problem: We are using WCF behaviours to provide common functionality for all our WCF services. As part of these behaviours we need to throw specific fault contracts. However unless these are explicitly included in the service contract they are not exposed in the WSDL and so they are not visible to the client (proxy generator). It seems odd for all services to have to include these fault contract references when their own code does not actually use them at all.

Potential Solution: Use the ‘KnownType’ attribute in the WCF behaviour. I believe this tells WCF to include the specified type during serialization. So by putting this in the behaviour dll will the type appear in the WSDL?

Automated Testing of WCF services

An outstanding issue on my project is that we don’t have the facility for our tester to test our WCF services without using our ASP.net front-end. The issue here is that we can (and do) put some code in our front-end that will mask or hide some parts of the services that we should be testing (our services should be accessible from any client). So what do we do? we could create a seperate basic client for each service, but this can take a lot of time and require a lot of work as the service evolves, it also faces the risk that we’ll mask and hide issues again. There are automated tools to generate a form to query the service but a lot of these don’t seem compatible with wshttp bindings; this would lead us to add another binding and endpoint just for testing the service (this might be what we have to do).

The latest information on the horizon is Visual Studio 2008 (orcas) apparently includes a WCF test client. Currently I haven’t used VS2008 so have no knowledge about this tool and can’t seem to find anything useful on the ol’ interweb. Anyone know anything about this tool?

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.

How to make a visual studio web reference pass message credentials

As part of my investigation into interoperability of our services I have spent some time trying to consume one of a sample web services without using “Add Service Reference” (part of .net 3.0).  The standard way of consuming a service in .net is to add a “Web reference”, which, behind the scenes, uses wsdl.exe to generate a proxy. The problem with this proxy is that it doesn’t support ws-* standards, and so we have to stop using wshttpbinding and rever to basic http binding. However this means that we lose the security context passing (user credentials in the message).

To solve this initial problem you can specify TransportWithMessageCredentials (see previous post), this places the credentials in the message and makes sure that the transport level is secured (using ssl). The next problem I encountered is that a web reference does not have the ability to pass message credentials. (There is a real gotcha here: the proxy class has a property called Credentials, this is the credentials to use for transport level security, not message level).

The way around this is detailed at  How to: Add Security Credentials to a SOAP Message
basically this involves installing  Web Services Enhancements (tested with 2.0 SP3). Version 2.0 of WSE is compatible with .net 1.1 (backwards compatibilty requirement). Once installed take the following steps:

  1. Add references to your client project to Microsoft.Web.Services2 and System.Web.Services
  2. Modify a web reference’s Reference.cs file so that the class inherits from Microsoft.Web.Services2.WebServicesClientProtocol
  3. Where a service call is made to the proxy first create a UsernameToken, specifying the required username, password and that the password is sent in plain text (ssl will secure it)
  4. Add the token to the client’s RequestSoapContext.Security.Tokens
  5. Call the web service
WebRef.Interface webClient = new WebRef.Interface();
UsernameToken user = new UsernameToken("username", "password", PasswordOption.SendPlainText);
webClient.RequestSoapContext.Security.Tokens.Add(user);
webClient.RequestSoapContext.Security.Timestamp.TtlInSeconds = 60;
string response=webClient.Operation("request");

How to setup a WCF service using basic Http bindings with SSL transport level security

In the .net 3.0 world you can use WS Http Bindings for your web services. Where your service has to be interoperable with other clients you can also expose a basic Http binding. This works fine, but you don’t automatically get things like security and passing of user credentials. To enhance the basic binding you can take advantage of different security settings; one of which is TransportWithMessageCredentials, this means that the transport of the messages is secured and so the message can include plain text credentials without compromising security. This requires a secure transport method, in this case https (SSL).

Setting up a Windows 2003 machine to use SSL (in IIS)

There are several ways of doing this, each with their own frustrations. The method below is the one which actually worked for me (after some methods that didn’t!).

  • Control Panel | Add or Remove Programs | Add/Remove Windows Components
  • Select Certificate Services
  • Install as a root
  • Open IIS
  • Right click on the default web site and select properties
  • Directory Security | Server Certificate
  • ‘Assign an existing Certificate’
  • Choose the certificate with the name that matches your machine name

Make Visual Studio use an SSL enabled host for the WCF Service
It does not appear to be possible to convert an existing Visual Studio website to an SSL one (and allow it to be debugged with SSL). Therefore you should:

  • “add existing website” to your solution.
  • Choose Local IIS
  • Create a new web application where desired
  • check the box to enable SSL (Use Secure Sockets Layer)
  • Right click the generated website project and select properties
  • Add a reference to your implementation project
  • Copy any existing web.config and *.svc files to your new website.

Now right click on the host project and select browse. (note: if the address does not include the filename you may need to manually add this in your browser) If you can see the service/wsdl and the address is https you have succeeded!


Modify your web.config to include a basic binding with transport level security

Use the following binding (play around with the different transport/message security modes if you like):

<basicHttpBinding>
<binding name=”basicHttp”>
<security mode=”TransportWithMessageCredential” >
<transport/>
<message clientCredentialType=”UserName”/>
</security>
</binding>
</basicHttpBinding>

Now in your <service> reference the new binding configuration

When is interoperability not interoperable?

Having spent the past few days ‘proving our web service interoperability’ I have found that interoperability is all very well, but it can be a right royal pain. Our web services are WCF services using all the latest .net bells and whistles and custom extensions. What I have found is that yes, our services are probably interoperable at a low level, so if you are happy playing about with SOAP messaging you can work with our web services, and in some cases happy working with even lower level abstractions. However the tooling just doesn’t seem to exist for the majority of platforms to automatically generate client proxies for our kinds of services.  Oh well, at least they’re interoperable at some level I suppose

Consuming a WCF Service using wshttp binding from a C++ client

Recently I have been testing the interoperability of our WCF services. Our services use wshttp bindings, custom security and some WCF extensions. My first target language is C++ and I’m starting off with VC++ in VS2005 with .net 3.0 on the machine.

VC++ does not have the same options for generating service references as C#. There seems to just be one method “Add Web Reference” that uses sproxy.exe behind the scenes. I tried this method first and ran into some problems. I then tried a rather interesting method where the proxy is generated as a C# class library that the C++ client uses to communicate with the web service.

  • Create your C++ client in VS2005
  • Add a new project to the solution of type C# class library
  • In the C# project add a service reference to your web service
  • in the C++ project add a reference to the C# project
  • in the C++ project add an app.config file
  • copy all the gubbins from the C# app.config into the C++ app.config
  • follow this guidance to make your C++ client use the app.config