WCF 4.5 Multiple Authentication Support

Multiple authentication support for a single endpoint is a feature which will be shipped with WCF 4.5. This is a very cool feature to make sure that we as developers can easier test our integration with multiple authentication scenarios.

When you are integrating systems, you always run into challenges where you have to simulate external systems through you Development, Test & Acceptance environments. Especially at your Development and Test environments. Building stubs is a way to simulate external systems. Unfortunately external systems mostly use different kind of authentication mechanisms, so your stubs need to support different kind of authentication mechanisms. Something want you don’t want is managing multiple stubs or provide different configuration files to make sure that your stub is able to support multiple authentication mechanisms.

Something what I tried was using the following configuration file:

<system.serviceModel>
   <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
   <bindings>
     <basicHttpBinding>
       <binding name="Integrated">
         <security mode="TransportCredentialOnly">
           <transport clientCredentialType="Windows"/>
         </security>
       </binding>
       <binding name="Basic">
         <security mode="TransportCredentialOnly">
           <transport clientCredentialType="Basic"/>
         </security>
       </binding>
     </basicHttpBinding>
   </bindings>
   <services>
     <service name="MyService">
       <endpoint address="IntegratedEndpoint" binding="basicHttpBinding" bindingConfiguration="Integrated" contract="IMyContract"/>
       <endpoint address="BasicEndpoint" binding="basicHttpBinding" bindingConfiguration="Basic" contract="IMyContract"/>
     </service>
   </services>
 </system.serviceModel>

I have defined two bindings to make sure that my service will be able to do Windows integrated security and basic authentication. Each binding is referenced by one endpoint. This way I am able to specify what kind of security mode I would like to use by specifying the right URL.

URL Authentication
http://localhost/MyService.svc/IntegratedEndpoint Windows
http://localhost/MyService.svc/BasicEndpoint Basic

The problem comes when I deploy this stub to a website which is configured for integrated security and another website which is configured for basic authentication. Before my WCF service will be hosted in IIS there is a validation check on my configuration. When I browse to my service which is hosted within my integrated website I will receive the following error:

“Security settings for this service require ‘Basic’ Authentication but it is not enabled for the IIS application that hosts this service”

So my configuration tells IIS that it will accept Basic authentication, but IIS isn’t supporting Basic authentication. Right now there are three ways to fix this issue:

  • Build multiple stubs with there own configuration file
  • Build one stub with multiple configuration files
  • Build one stub with one configuration file and use xml preprocess

Build multiple stubs with there own configuration file

Well this isn’t a real option, right? to much code redundant so we will skip this one.

Build one stub with multiple configuration files

image

When you build your installation package you make sure the right configuration file is included in your package. This means you have to manage multiple configuration files

Build one stub with one configuration file and use xml preprocess

Xml preprocess provides the opportunity to write if- else statements in your configuration file. This way you can process your configuration file using parameters to make sure the right configuration file will be produced for the right website.

So all this stuff to deploy a stub which should run in IIS and should support multiple authentication protocols. The problem is the difference between settings in your web.config and IIS. In WCF 4.5 they offer you the possibility to inherit the settings from IIS into your configuration file. So when you website is running integrated security your service will run with integrated security. This way you have one stub, one configuration file which can be deployed to multiple websites with different authentication protocols.

Take a look at a post of Ido Flatow who describes how to configure your configuration file.

WCF Web API preview 6

Today Microsoft released preview 6 of WCF Web API. Check codeplex for the new bits. There is support for JSONP now!

Regards,

Dennis

WCF Express Interop

How cool is that? Interop with:

  • Oracle WebLogic
  • Oracle Metro
  • IBM WebSphere
  • Apache Axis2

Microsoft makes this possible with the new WCF Express interop bindings. Unfortunately i am in a total Microsoft environment Glimlach, so i am not able to test them very soon myself.

WCF services and shared assemblies

I often see situations on projects where they have design challenges with multiple webservices who share the same datacontracts (DTO). I already wrote a post about the separation of the service contract and the DTO’s, but i would like to extend that post with my vision on how we should work with mutiple services build on top of the same DTO’s.

To illustrate this I have build two WCF services which both have a reference to the DTO project called MyDataContracts. The solution for my services looks like this:

ServiceImplementation

Project 1 & 3 are service contracts and service implementations and project 2 contains the shared DTO’s.

The service contracts are very simple

[ServiceContract]
public interface ICustomerService
{
    [OperationContract]
    Customer GetCustomer(int value);
}
[ServiceContract]
public interface IInvoiceService
{
    [OperationContract]
    Invoice GetInvoice(int invoiceId);
}

The invoice DTO is implemented below

[DataContract]
public class Invoice
{
    int invoiceId = 0;
    Customer client;

    [DataMember]
    public int InvoiceId
    {
        get { return invoiceId; }
        set { invoiceId = value; }
    }

    [DataMember]
    public Customer Customer
    {
        get { return client; }
        set { client = value; }
    }
}

Because the invoice DTO has a datamember of the type customer the clients who want to interact with the invoice service have to know how a customer DTO will look like.

So that’s it for the service side. Now we take a look at the client side. When I consume services I usually create a service agent project which will be responsible for handling the calls to the services. This way I only have to implement exception handling once for the communication with my services. So my service agent project has two service references (two proxies). These two proxies will receive there own version of the customer DTO when I generate the proxy in the standard way. As you can see in the object browser below, both proxies have a Customer DTO generated. This can give you some annoying issues especially when you have to map values to your customer DTO and you have to pick a different one depending on the service you are communicating with.

ObjectBrowser

My client solution looks like this

ClientApplication

The first project is just a console application which interacts with my second project the service agent. I have created a service agent class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MyServiceAgents.CustomerProxy;
using MyServiceAgents.InvoiceProxy;
using System.ServiceModel;

namespace MyServiceAgents
{
    public class ServiceAgent
    {
        public Customer GetCustomer()
        {
            CustomerServiceClient proxy = new CustomerServiceClient();

            try
            {
                return proxy.GetCustomer(1);
            }
            catch (FaultException ex)
            {
                // catch any faultexception from the service
            }
            catch (CommunicationException cex)
            {
                // ...
            }
        }

        public Invoice GetInvoice()
        {
            InvoiceServiceClient proxy = new InvoiceServiceClient();

            try
            {
                return proxy.GetInvoice(1);
            }
            catch (FaultException ex)
            {
                // catch any faultexception from the service
                throw new Exception();
            }
            catch (CommunicationException cex)
            {
                // ...
            }
        }
    }
}

The service agent has two methods. Each method is responsible to communicate with one of the two services. To make sure my proxy classes are available i have to add the following using statements

  • using MyServiceAgent.CustomerProxy
  • using MyServiceAgent.InvoiceProxy
    Adding these using statements will give us the problem of ambiguous classes.

Ambiguous

Well take a look at what happened right now. On the right side we see the customer & invoice service. The service project references the contracts project which contain two DTO’s. On the left side I have the service agent project which contains two service references. Adding these service references added a proxy for both services and DTO’s which are needed for the communication. The customer DTO is created twice.

Overview1

To resolve this issue you could use a shared assembly for the DTO’s. You have to make sure that when the service reference is added on the client project it doesn’t generate any DTO’s anymore. To make this possible you have to share your DTO assembly with your consumers, which looks fine to me. This will give you the following situation.

Overview2

I hope that sharing an assembly doesn’t need any explanation. To make sure that adding a service reference doesn’t generate any DTO’s you only have to add a reference from your service agent project to the DTO assembly. This way Visual Studio knows how to handle the generation of your service reference. To be sure click on the advanced button when you add a service reference.

VisualStudioSetting

Make sure the checkbox ‘Reuse types in referenced assemblies’ is enabled and you are good.

This solution can be related the the following SOA pattern: Canonical schema The DTO’s are set as standard across service contracts within an inventory boundary.

Regards,

Dennis