Silverlight, WCF & TransportWithMessageCredential Security

This post is made from a train where I got bored and noticed an email in a discussion list folder that mentioned that Silverlight could do WCF authentication using TransportWithMessageCredential security.

I’m not at all sure if this is a new thing and suspect that it’s more likely that it’s always been there and I’d just missed it but it fell into the category of “learning something new every day” 🙂

Regardless, I had a quick experiment with it – essentially TransportWithMessageCredential means that you’re using the transport ( e.g. in Siverlight this means HTTPS ) to ensure the privacy of the message that you’re transmitting and, because of that, it’s ok to transfer some credential as part of the message.

This is similar to using basic/digest authentication over HTTPS except in that case it’s the HTTP protocol that’s transporting the credentials whereas in this case it’s the SOAP message that’s transporting them.

One of the nice things about that is that those credentials can flow straight into WCF code in order to validate them on the server side. So, if I have a server side contract;

[ServiceContract]
public interface IService
{
  [OperationContract]
  string DummyOperation();
}

and I then implement that;

public class Service : IService
{
  public string DummyOperation()
  {
    return ("Hello World");    
  }
}

and, more importantly, configure it ( note – not sure if I could use wsHttpBinding here with some bits switched off but I chose to use a custom binding );

  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="myConfig">
          <textMessageEncoding/>
          <security authenticationMode="UserNameOverTransport"/>
          <httpsTransport/>
        </binding>
      </customBinding>
    </bindings>
    <services>
      <service name="Service"
               behaviorConfiguration="ServiceBehavior">
        <!-- Service Endpoints -->
        <endpoint address=""
                  binding="customBinding"
                  contract="IService"
                  bindingConfiguration="myConfig"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
          <serviceCredentials>
            <userNameAuthentication customUserNamePasswordValidatorType="MyValidator,ValidationBits"
                                    userNamePasswordValidationMode="Custom"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

with the MyValidator type looking like;

public class MyValidator : UserNamePasswordValidator
{
  public MyValidator()
  {
  }
  public override void Validate(string userName, string password)
  {
    if ((userName != "Foo") || (password != "Bar"))
    {
      throw new UnauthorizedAccessException();
    }
  }
}

and then I can just add a service reference to the service from the Silverlight client and call it as in;

      ServiceClient proxy = new ServiceClient();

      proxy.ClientCredentials.UserName.UserName = "Foo";
      proxy.ClientCredentials.UserName.Password = "Bax";

      proxy.DummyOperationCompleted += (s,e) =>
        {
          int x = 10;
        };

      proxy.DummyOperationAsync();

Not exactly “revolutionary” but one that I hadn’t explicitly experimented with before so it interested me on the train 🙂 and I thought I may as well share.