Archive for WCF

WCF Security – Part 1: Message & Transport Security

Dec 16

WCF has a huge security component to it (as rightly it should). The technology is massively configurable to support almost any security scenario one can dream up. Unfortunately this also makes it massively hard to learn and implement successfully and many developers tend to work around the security rather than learn how to implement it correctly. With a bit of knowledge WCF security is not nearly as intimidating as one may think.

There are several security concerns to deal with in any communication technology. The top two most common concerns  are: making sure that no one can read, modify, or replay a sensitive message and ensuring that a caller is authenticated  to use the system and authorized to access the resources they are allowed to access (and denied access to the ones they are not allowed to access of course). The other concerns are usually around Availability (i.e. making sure the service is resistant to Denial Of Service attacks) and Auditing (being able to log and monitor security events).

Message Protection

Protection of the traffic in transit is easy to use and is typically turned on by default (basicHTTPBinding has no security by default). There are two choices to make with securing traffic: Transport or Message security. Transport security relies on security builtin to the protocol you are using (e.g. HTTPS for HTTPBindings and TLS for TCP bindings). Message security lets WCF sign and encrypt messages and then sends it across the transport.

Transport Security:
+Interoperability: Neither party in a communication need to support WS-Security specifications
+Potentially better performance
-Security is point to point. If a message is routed through an intermediary it will not be guaranteed to be secure (i.e. many load balancers accept SSL traffic, decrypt it, and send it unencrypted to a node in its array)
-Supports a smaller set of credentials and claims used for authentication
-All or nothing: A message is either encrypted or it is not

Message Security:

+End to end security: message security survives being routed through intermediaries
+Allows partial message signing/encryption so that only messages that need protection can be protected
+Transport independent: Message security can be used with any transport protocol
+supports a large set of credentials and claims
-May reduce performance as each message is secured and can not take advantage of hardware acceleration
-Not as interoperable as both sides must implement the WS-Security specification

 

Binding

Transport mode support

Message mode support

basicHTTPBinding

HTTPS

HTTP basic authentication
WS-Security

wsHTTPBinding

HTTPS

WS-Security
SOAP message with credentials sent over HTTPS transport security

wsDualHTTPBinding

None

WS-Security

netTCPBinding

TLS over TCP

WS-Security

netNamedPipeBinding

Negotiated (best compatible support is used)

None

netMSMQBinding

RC4 or AES (default is RC4). Messages signed with receiving queues public certificate.

WS-Security

wsFederationHttpBinding

HTTPS

WS-Security

 

There are also a few other approaches as well. There is the hybrid TransportWithMessageCredential which the client credentials are provided at the message level and the remainder (the message itself and service authentication) is secured by the transport. The other type is TransportCredentialOnly which is ONLY for basicHTTPBinding that does mutual authentication at the transport level.    

Binding

Transport mode support

Message mode support

TransportWithMessageCredential support

BasicHttpBinding

Yes

Yes

Yes

WSHttpBinding

Yes

Yes

Yes

WSDualHttpBinding

No

Yes

No

NetTcpBinding

Yes

Yes

Yes

NetNamedPipeBinding

Yes

No

No

NetMsmqBinding

Yes

Yes

No

MsmqIntegrationBinding

Yes

No

No

wsFederationHttpBinding

No

Yes

Yes

From http://msdn.microsoft.com/en-us/library/ms731172.aspx

Up Next: Authentication


Filed Under: Security, WCF

Creating A Global Error Handler In WCF

Jun 24

One of the key things in any application is to have an exception handler that logs any unhandled exception so that the application can be debugged in the future.

In many applications I see this done by wrapping every external method in a try / catch block. While this works it has several drawbacks. First of all it is a pain to type the same code over and over again. It is easy to forget to add the try / catch / log block one one method. The biggest pain is if you need to change the way you log you have to change every single instance of that code.

In WCF there is an easy way to intercept all exceptions and log them via adding in by implementing a few simple interfaces that extend WCF.

The first one is the IErrorHandler interface:

 public class ErrorHandler : IErrorHandler
    {
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
          
        }

        public bool HandleError(Exception error)
        {
            if (!EventLog.SourceExists(“Operations”)) EventLog.CreateEventSource(“Operations”, “Application”);
            EventLog.WriteEntry(“Operations”, error.ToString());
            return false;
        }
    }

The HandleError() method will be called whenever an exception occurs. Here we log to the event log and then return false so the error can continue to propagate up the chain. The ProvideFault() method can be used to transform exceptions into faults but for this example we are not going to do any rewriting of the fault message that is to be returned and will leave the method blank.

Next we have to write a service behaviour that will allow us to add our custom error handler for each channel we have a service running on. This is done by implementing the IServiceBehavior interface.

public class ErrorServiceBehavior : IServiceBehavior
    {
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {

        }

        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            ErrorHandler handler = new ErrorHandler();
            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(handler);
            }
        }
    }

Here we are enumerating all channels and adding the error handler to the collection. We do not need to change anything in the other methods of the interface.

Now we need to do is create a simple behaviour extension element so that we can use the error service behaviour in our config.

 public class ErrorHandlerBehavior : BehaviorExtensionElement
    {
        protected override object CreateBehavior()
        {
            return new ErrorServiceBehavior();
        }

        public override Type BehaviorType
        {
            get { return typeof(ErrorServiceBehavior); }
        }
    }

Lastly we can put the behaviour in the config file for our service.

 <system.serviceModel>
    <extensions>
      <behaviorExtensions>         <!—Add in our custom error handler -->
        <add name="ErrorLogging" type="Dispatch.Service.ErrorHandlerBehavior, Dispatch.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c62bf877ee633f38" />
      </behaviorExtensions>
    </extensions>
    <services>
      <service name="Dispatch.Service.DispatchService" behaviorConfiguration="Dispatch.Service.Service1Behavior">
        <endpoint address="" binding="wsHttpBinding" contract="Dispatch.Service.IDispatchService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Dispatch.Service.Service1Behavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
          <ErrorLogging /> <!—Name from behaviorExtensions Element -->
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

As you can see I added the extension to the Extensions element and then placed the name in the behaviour. My assembly is strong named but it should not be required to implement this behaviour (you should just be able to use PublicKeyToken=null if it is not strong named).

Filed Under: WCF

Diagnosing The “Failed to generate code for the service reference ‘YourReferenceName’.” Error

Mar 23

Sometimes on a WCF project you will get the error:

Failed to generate code for the service reference ‘YourReferenceName’.  Cannot import wsdl:portType  Detail: An exception was thrown while running a WSDL import extension:

This is usually caused by a contract mismatch. For us it is when the assembly that contains our data contracts on the server and client are different.

First thing to check is the output window but if nothing is there I have found using svcutil.exe from a visual studio command prompt to generate the proxy on the command line gives me the info I need to diagnose the problem.

svcutil.exe /language:cs /out:TempProxy.cs /config:app.config /reference:DataContracts.dll http://address/to/service.svc

Flag Break Down:

/language What language to generate in (cs, vb, or, c++)
/out The file we want our proxy code in (this is a new file I am using)
/config Generate a new config file. 
/references The file that contains our datacontracts/service contracts that we want to re-use in our application.

There are a ton more flags but this is usually sufficient to get the message of why it is having issues generating the proxy. The other flags can be found by searching for svcutil.exe on MSDN.

Filed Under: WCF

Debugging WCF

Aug 6

I think WCF is a pretty sweet technology stack. It makes things work with each other quite easily….. until you use it for more than the default it was setup to handle. This usually results in some strange and hard to diagnose error messages.

The #1 tip I have so far is to use the SvcConfigEditor.exe file that comes with the Windows SDK to edit your configuration files as it allows you to edit the configuration in a simple and visual fashion and makes it much harder to make errors in your config file.

Problem: The content type text/html; charset=utf-8 of the response message does not match the content type of the binding.
Usual Reason: Your service is returning an HTTP error and not a WCF message. This most often occurs because your config file is not valid or the page is not found.
Solution: The first thing is to narrow down the error by opening the service in your browser and making sure it can return wsdl (i.e. http://localhost/MyFirstService/HelloWorldService.svc?wsdl). This will point you to the problem 99% of the time (and for me 99% of the time was I put in some configuration that was not valid)
Problem: The Server was unable to process the request due to an internal error.
Usual Reason: The service probably threw an exception so the message could not be returned.
Solution: On the server turn on IncludeExceptionDetailInFaults so that the client can see the error message if that is what you desire. Otherwise fix the reason why the application is throwing an exception.
Problem: The message could not be processed. This is most likely because the action ‘…’ is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings
Usual Reason: The server says it is behaving in one fashion and the client expects another.
Solution: You could look over the client and server configuration files until your eyes bleed or take what I have found to be the easy way out: Use the SvcConfigEditor.exe to regenerate your client configuration file.
Problem: Exceeded MaxItemsInObjectGraph quota. Maximum number of items that can be serialized or deserialized in an object graph is ’65536′.
Usual Reason: There amount of objects to be serialized exceeds the default limit. This is probably a limit put in place to prevent a denial of service attack so you can set this to be a reasonable level for your application.
Solution:

Change the server/client to increase the maximum objects serialized

Change the server:
<service behaviorConfiguration=”LargeMessageBehaviour” name=”MyFirstService.HelloWorldService”>
        <endpoint address=”
http://localhost/MyFirstService/HelloWorldService.svc
                    binding=”basicHttpBinding”
                    contract=”MyFirstService.IHelloWorldService” />
      </service>

<behaviors>
  <serviceBehaviors>
    <behavior name=”LargeMessageBehaviour”>
      <dataContractSerializer maxItemsInObjectGraph=”6553600″ />
    </behavior>
  </serviceBehaviors>
</behaviors>

Change the client:

 <client>
      <endpoint address=”
http://localhost/MyFirstService/HelloWorldService.svc
        behaviorConfiguration=”LargeMessageBehavior” binding=”basicHttpBinding” />
</client>

<behaviors>
  <endpointBehaviors>
     <behavior name=”LargeMessageBehavior” >
         <dataContractSerializer maxItemsInObjectGraph=”6553600″/>
      </behavior>
   </endpointBehaviors>
</behaviors>

Problem: System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly
Usual Reason: This is the really generic error message I find and can be for multiple reasons. So far I have only had it when hosting a service in IIS.
Solution: As there are several possible causes there are several possible solutions
1. If you are sending lots of data IIS will reject anything over a certain limit by default. You can change this setting with:
<system.web>
    <httpRuntime maxRequestLength=”734000″/>
</system.web>
2. If your request takes a long time to process IIS can timeout. You can change this via:
<system.web>
    <httpRuntime executionTimeout=”500″ />
</system.web>
3. Something else went wrong and instead of responding the webserver just decided to shut down. In this case you will have to enable tracing on the server and or client to narrow down the error (see debugging steps below)


Debugging Steps
Here are the usual steps I take to narrow down a problem. Each problem is unique though so some of these steps may not apply:
1. Open up the service wsdl in a browser to make sure that the service is working: (i.e. http://localhost/MyFirstService/HelloWorldService.svc?wsdl).
2.  Often issues arise because of configuration issues. I often find myself editing the configuration files using the SvcConfigEditor.exe file that comes with the windows SDK which can help you find the right spot to make configuration changes.
3.   I also find that mirroring my changes from the server behaviour to the client is a source of issues. You can use the SvcConfigEditor.exe tool to generate the client configuration based on a server configuration file.
4.   Enable tracing. This will allow you to log a lot more information about the client/server interaction and usually reveals more details about an issue. This is easiest to enable via the SvcConfigEditor.exe again and the logs can be easily viewed with the SvcTraceViewer.exe file (Both are part of the Windows SDK)

Filed Under: WCF

Configuring WCF Contract Behaviour

May 19

One thing that bugged me with WCF was when you auto generated your proxy client (using add/update service reference), that collections were turned into arrays. Granted it is trivial to convert them back to a collection if need be it is still a pain.

Randomly I discovered that if you right click on the service reference and selecting “Configure Service Reference” (who knew!) that you can change this behaviour for both collections and dictionaries to be several different types:

 

 

Another nice item was to be able to change the access levels for generated classes and being able to add async operations only if you wanted them (I disliked how they were always there but rarely used with the web service proxies).

Filed Under: WCF

WCF Message Streaming

Apr 14

In my previous post WCF And Large Messages. I mentioned there was a better way to send large data. As I have been getting a lot of traffic on this topic here is the improved methodology:

One of the really sweet features of WCF is to allow the streaming of messages between client and server. By default messages are buffered and once completely built they are sent.

While this works great for small messages once you start sending large amounts of data (in my case a 50-70Mb file) it really pays off. For my case sending data as a large message took an average of 23.3 seconds in the standard buffer and burst mode method described here. Doing this via streaming only took an average of 4 seconds using the streaming method.

Streaming is only supported under the basicHttpBinding, netTcpBinding, and netNamedPipeBinding bindings. If you are hosting your service in IIS6 your only option is to use basicHTTPBinding (or create your own binding but that is outside the scope of this post). If you are hosting your IIS7 then you will be able to use the TCP, named pipes, and the msmq bindings as well.

To enable streaming was surprisingly simple. All I had to do was create a new binding configuration:

  <basicHttpBinding>
        <binding name="StreamingFileTransferServicesBinding"
                 transferMode="StreamedRequest"
                 maxBufferSize="65536"
                 maxReceivedMessageSize="204003200"  />
  </basicHttpBinding>

And then set my service to use that binding configuration:

      <service behaviorConfiguration="MyBehaviour" name="MyStreamingService">
        <endpoint address=""                   binding="basicHttpBinding"                   bindingConfiguration="StreamingFileTransferServicesBinding"                   contract="IMyStreamingService" />
        <endpoint address="mex"                   binding="mexHttpBinding"                   contract="IMetadataExchange" />
      </service>

To dissect this a bit I have setup a buffer size and a maxMessageReceive size which controls how much data is buffered before it is sent and how big those messages can be. To be honest I have not played with these settings very much yet so you will probably want to tweak these to your own situations.

Also in the binding configuration there are several different streaming types we can setup:

Streamed – Both in and out messages are streamed
StreamedRequest – Messages sent from client to server are streamed
StreamedRespone – Only messages returned from the server to the client are streamed
Buffered – This is the default of buffering all data and sending it in one burst

A BIG thing to note is that when using streams the only allowed data types are Message, Stream, or an IXMLSerializable implementation for ALL methods in your service! If we use “Streamed” as our transfer mode then we would need to have BOTH our input parameters and our return value be one of these types. If you just want to send data and return back some small data object or primitive then use StreamedRequest or StreamedResponse.

Onwards to code!

 

Function ProcessFile(ByVal data As Stream) As DataContracts.ValidatedAuthority

As you can see here my interface is pretty simple. It takes in a stream of data and returns a simple object that shows how the file processing went.

As I mentioned before that because we are using streaming that all methods must take only Streams, Message, or IXMLSerializeable as parameters. If you want to have methods that do not require this then create a new service that does not use the streaming behaviour.

Now if you are hosting in IIS you will still need to let the HTTPRuntime that you are sending large data with: <httpRuntime maxRequestLength=73400 executionTimeout=“100 /> (Or whatever settings you think are appropriate).

A little housekeeping note is that you will need to dispose the stream on both the client and server. This is because there are actually two streams in two different app domains so both client and server will need to treat them as such.

Also for completeness here is my entire service model config section:

<system.serviceModel>
    <services>
      <!--Streaming Service-->      <service behaviorConfiguration="MyBehavious" name="MyStreamingService">
        <endpoint address=""                  binding="basicHttpBinding"                  bindingConfiguration="StreamingFileTransferServicesBinding"                  contract="IMyStreamingService" />
        <endpoint address="mex"                  binding="mexHttpBinding"                  contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>             <serviceBehaviors>                  <behavior name="MyBehavior">
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="true" />
          </behavior>              </serviceBehaviors>        </behaviors>        <bindings>
      <basicHttpBinding>
        <binding name="StreamingFileTransferServicesBinding"
                 transferMode="StreamedRequest"
                 maxBufferSize="65536"
                 maxReceivedMessageSize="204003200"                 />
      </basicHttpBinding>        </bindings>  </system.serviceModel>
Filed Under: WCF

WCF And Large Messages

Mar 30

****Just a forewarning that this is an interim step I took to move large messages. In my next post I will talk about streaming data via WCF which works a lot better for the scenario described here*****

For one of my projects we are moving a large file to our service via WCF. By default WCF only allows small messages and arrays to be processed but in my case I am moving a 50-70Mb byte array around. There are a few things you will need to do to get large messages to move around.

The first thing you will probably notice is that when trying to send a large file the connection will just close or return some strange error. This is due to the fact that either the message will timeout or exceed the maxReceivedMessageSize for the binding. This can be modified by adding a binding configuration that sets the send/receive timeouts and the message size.

<

bindings>
  <
wsHttpBinding>
    <binding name=FileTransferBinding
    closeTimeout=00:01:00
    openTimeout=00:01:00
    receiveTimeout=00:10:00
    sendTimeout=00:01:00
    maxReceivedMessageSize=73400320 > <!–70MB–>
          <
readerQuotas maxArrayLength=73400320 />
    </
binding>
  </
wsHttpBinding>
</
bindings>

WCF also has default limits on the maximum size of an array so I set the maxArrayLength option on the binding to be quite large.

Next all you have to do is set the endpoints binding configuration to be the configuration we just created:

<

endpoint address=“” 
             
binding=wsHttpBinding 
             
bindingConfiguration=FileTransferBinding
             
contract=MyProj.IService />

Now one thing that I would recommend would be to use a binary binding like netTCP instead of a HTTP based binding for a case like this. Unfortunately if you are hosting your service in IIS6 you can only use HTTP based bindings (in IIS7 you can use TCP based bindings in addition to HTTP).

Also if you are hosting your service in IIS you will need to adjust the httpRuntime to allow large files as well. This can be done in the <system.web> section like so: <httpRuntime maxRequestLength=73400 />

 

For the sake of completeness here is my completed <system.serviceModel> section:


<
system.serviceModel>
  <
services>
    <
service name=MyApp.Service.FileProcessor 
               
behaviorConfiguration=MyApp.Service.FileProcessorBehavior>

      <

endpoint address=“”
                   
binding=wsHttpBinding 
                   
bindingConfiguration=FileTransferServicesBinding
                   
contract=MyApp.Service.IFileProcessor />

      <

endpoint address=mex
                   
binding=mexHttpBinding 
                    contract
=IMetadataExchange/>

    </

service>
  </
services>
 
  <
behaviors>
    <
serviceBehaviors>
      <
behavior name=MyApp.Service.FileProcessorBehavior>
       
<serviceMetadata httpGetEnabled=true/>
       
<serviceDebug includeExceptionDetailInFaults=true/>
      </
behavior>
    </
serviceBehaviors>
  </
behaviors>

  <bindings>
    <
wsHttpBinding>
      <binding name=FileTransferServicesBinding
                  closeTimeout=00:01:00
                  openTimeout=00:01:00
                  receiveTimeout=00:10:00
                  sendTimeout=00:01:00
                  maxReceivedMessageSize=73400320
        <
readerQuotas maxArrayLength=73400320 />
      </
binding>
    </
wsHttpBinding>
  </
bindings>

</

system.serviceModel>

 

Now as with everything there is more than one way to toss a cat off a bridge. One thing to add to this would be compression to shrink the data being transferred (if the data you are transferring compresses well at least).

WCF has support for streaming data instead of our current buffer approach. Our services code will not kick in until we have received all of the data. If we used a stream approach we could start processing data as it arrives.

 

 

Filed Under: WCF