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.

Advertisements

WCF under the hood

When you are a .NET developer and you are working with Windows Communication Foundation (WCF) and you really want to know how it works under the hood than you have to take a look at the blog of Carlos Figueira. He has a lot of posts on extending the framework. With his posts on extending the framework you also get a look how the framework is build. This is one of the posts I like. It’s not an implementation you would see often in production environment, but it’ shows very good how you can extend the framework.

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

Designing WCF services

Hi all,

I have been working for a while with WCF and still want to learn more about how to design better WCF services. I found a great post i would like to share with you: patterns for flexible wcf services. I hope you like the post as much as i do.

Regards,

Dennis

WCF and IsWrapped MessageContracts

The IsWrapped property on a messagecontract is keeping me busy. When working with WSSF it’s forcing you to set the IsWrapped property to true when you have more than one element in your message contract. This is because this required by the WS-I Basic profile1.1 standard. So you set the property to true and don’t have any idea what this will do to the proxy which is generated for you. In this post i will describe four possible scenarios and there effect on the proxy which is influenced by the choice you make. The possible scenarios are summarized in the table below:

  Request IsWrapped  Response IsWrapped 
Scenario 1 True  False 
Scenario 2  False True 
Scenario 3 False False
Scenario 4 True True

 

Well I desgined a simple service called CaseService. This service implements the ICaseService interface. This interface contains one operation RetrieveCase which accepts a casenumber (string) as input paramter and returns a Case object.

The messagecontract I used are: RetrieveCaseRequest and RetrieveCaseResponse.

Scenario 1

In this scenario I set the property IsWrapped of the RetrieveCaseRequest to true and the IsWrapped property of the RetrieveCaseResponse to false. When I build this service and generate a proxy for this service this will give me the following code (I stripped code which is irrelevant for this post):

public WCFService.Client.Proxy.Case RetrieveCase(WCFService.Client.Proxy.RetrieveCaseRequest RetrieveCaseRequest)
        {
            WCFService.Client.Proxy.RetrieveCaseRequest1 inValue = new WCFService.Client.Proxy.RetrieveCaseRequest1();
            inValue.RetrieveCaseRequest = RetrieveCaseRequest;
            WCFService.Client.Proxy.RetrieveCaseResponse retVal = ((WCFService.Client.Proxy.CaseService)(this)).RetrieveCase(inValue);
            return retVal.Case;
        }

The extra generated messagcontract

[System.ServiceModel.MessageContractAttribute(IsWrapped = false)]
    public partial class RetrieveCaseRequest1
    {

There are two Request MessageContracts generated: RetrieveCaseRequest and RetrieveCaseRequest1. The RetrieveCaseRequest1 is a wrapper for the RetrieveCaseRequest. It looks like that the proxy will balance the request and response to the same IsWrapped setting. They are both send over the line with IsWrapped set to false.

The proxy will send the RetrieveCaseRequest1 (IsWrapped=false) and will receive RetrieveCaseResponse (IsWrapped=false). The RetrieveCaseRequest method in the proxy will accept a request messagecontract as input.

Scenario 2

In this scenario we will switch the IsWrapped settings. For the Request it will be set to false and for the response it will be set to true. Scenario 2 will give us the situation which is vica versa of scenario 1. There is one Request MessageContract and there are two Response MessageContracts: RetrieveCaseResponse and RetrieveCaseResponse1. The RetrieveCaseResponse1 is used as a wrapper contract for the RetrieveCaseResponse. Also notice the input parameter of the method RetrieveCase in the proxy. It’s a CaseNumber (string) and not a messagecontract like in scenario 1. It will wrap it into a messagecontract before sending it to the service.

public WCFService.Client.Proxy5.RetrieveCaseResponse RetrieveCase(string CaseNumber)
        {
            WCFService.Client.Proxy5.RetrieveCaseRequest inValue = new WCFService.Client.Proxy5.RetrieveCaseRequest();
            inValue.CaseNumber = CaseNumber;
            WCFService.Client.Proxy5.RetrieveCaseResponse1 retVal = ((WCFService.Client.Proxy5.CaseService)(this)).RetrieveCase(inValue);
            return retVal.RetrieveCaseResponse;
 }

Scenario 3

In the third scenario i have set both message contracts (request and response) to false. This results in the following proxy method:

public WCFService.Client.Proxy3.Case RetrieveCase(string CaseNumber)
        {
            WCFService.Client.Proxy3.RetrieveCaseRequest inValue = new WCFService.Client.Proxy3.RetrieveCaseRequest();
            inValue.CaseNumber = CaseNumber;
            WCFService.Client.Proxy3.RetrieveCaseResponse retVal = ((WCFService.Client.Proxy3.CaseService)(this)).RetrieveCase(inValue);
            return retVal.Case;
        }
As you can see, it will  accept a casenumber as input and a case object as return parameter. The proxy will wrap a messagecontract around the type before sending it to the service and strips the messagecontract before returning the response to the consumer of the proxy. Remember that you don’t always have the option to set the iswrapped property to false. When your messagecontract has multiple elements it will need the iswrapped property set to true.

Scenario 4

In this scenario I will set for both the Request and Response messages the IsWrapped property to true.

public WCFService.Client.Proxy2.Case RetrieveCase(string CaseNumber)
{
            WCFService.Client.Proxy2.RetrieveCaseRequest inValue = new WCFService.Client.Proxy2.RetrieveCaseRequest();
            inValue.CaseNumber = CaseNumber;
            WCFService.Client.Proxy2.RetrieveCaseResponse retVal = ((WCFService.Client.Proxy2.CaseService)(this)).RetrieveCase(inValue);
            return retVal.Case;
        }

As you can see this scenario contains the same proxy method as scenario 3.

I have experienced three of the four scenarios on projects and i was wondering how is it possible that my proxy is looking different when i am switching the iswrapped properties. I hope that this post will give you some information about the iswrapped property and will give you some ideas when you are running in the same kind of proxies with different faces.

Regards,

Dennis