Username Authentication over basicHttpBinding with WCF’s ChannelFactory Interface

HTTP/HTTPS holds good (add no session management) for lot of people today & they prefer using them as their transport protocol for WCF Services. Many a time users connecting with your service are outside your domain so you will like to authenticate them with username / password. This is where WCF makes things difficult.

There is some support shown here for self hosted service (but I have my own reservations over that as IIS is the most preferred hosting mechanism when it comes to HTTP). Let me split this post into 2 parts – assigning credentials to client & authenticating those credentials on server (N.B. my writing is on top of custom binding + channel interface, no Add Service Reference used).

1) Adding credentials on client side via channel factory interface:

ClientCredentials is part of System.ServiceModel.Description.ClientCredentials (System.ServiceModel). Problem is ChannelFactory has a readonly ClientCredentials Property (not when you generate proxy by inheriting from ClientBase this is simplified for you). Luckily there is a workaround. To start with you can instantiate it & assign required values

ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = “Niraj”;
loginCredentials.UserName.Password = “Password123”;

Now ClientCredentials are by default endpoint behaviors, so you have remove the default one & attach the newly created one. Below code shows that

var defaultCredentials = factory.Endpoint.Behaviors.Find<ClientCredentials>();
factory.Endpoint.Behaviors.Remove(defaultCredentials); //remove default ones
factory.Endpoint.Behaviors.Add(loginCredentials); //add required ones

 2) Authenticating Credentials on Server Side: This is where things get tricky and you need to use something probably you have heard of but haven’t tried yet, a WCF security mode called – TransportWithMessageCredential (N.B. It’s not currently possible to handle this scenario using Basic Authentication of IIS (transport clientCredentialType), though you can easily do it for REST).

Step 1 is your customize your binding (this has to be done on both Server & Client configurations)

<bindings>
      <basicHttpBinding>
        <binding name=”usernameHttps”>
          <security mode=”TransportWithMessageCredential”>
            <message clientCredentialType=”UserName”/>
          </security>
        </binding>
      </basicHttpBinding>
</bindings>

Note that the above would force you to use HTTPS but anyways that’s a recommended approach also. Now it’s time to go to your service and specify the service credentials as shown below, here we use custom authenticator but you could as well used provider model of ASP.NET,

<serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode=”Custom”
              customUserNamePasswordValidatorType=”…” />
</serviceCredentials>

public class CustomPass : UserNamePasswordValidator //System.IdentityModel.dll
{
        public override void Validate(string userName, string password)
        {
            //your validation here, throw exception if invalid user
        }
}

That’s it. You are all set. Fire you client & you have username authentication over HTTPS. Hope that helps.

(N.B. You can check my blog entry about how to configure HTTPS for WCF on IIS)

20 thoughts on “Username Authentication over basicHttpBinding with WCF’s ChannelFactory Interface

  1. I don’t get step 1, why this way if you just can set it like this:

    factory.Credentials.UserName.UserName = “somthing”;
    factory.Credentials.UserName.Password = “somthing”;

    Regards,
    CA

  2. Hi CA,

    I already mentioned that while using channel factory interface, – “Problem is ChannelFactory has a readonly ClientCredentials Property”. I guess what you are saying will only work if you are using Add Service Reference & ClientBase inheritance, which would handle it for you behind the covers. In my scenario I have some limitation on using Add Service Reference.

    1. True that ClientCredetials is readonly, but Credentials.UserName “Gets a credential object that you can use to set the user name and password…”

    1. Custom validator belongs to development server‘s or IIS process (depend on how you configured the service‘s project). Put breakpoint on row where you are calling the service and attach to WebDev.WebServer (if you are working with development server) or w3p (when project is using IIS virtual directory). Breakpoints will hit after that.

  3. I’m stuck with what to set customUserNamePasswordValidatorType to. I’ve put my custom authenticator in it’s own file called Authentication.cs and it’s the same namespace as my service. I’ve tried the following values:

    =”MyNameSpace.Authentication”
    =”MyNameSpace.Authentication, Authentication”
    =”Authentication”
    =”MyNameSpace, Authentication”

    All of the above produce errors along the lines of “cannot find”.

    1. It’s always the way… just after my last post where I ask for help, I’ve found the solution to my problem. Solution to my little problem is simply this

      customUserNamePasswordValidatorType=”MyAssembly.MyCustomValidator, MyAssembly”

      I really must be tired to not have figured that out earlier…

  4. Hi there :

    I am bit late to the party. Just got few queries as follows :

    1. Can I implement this whole thing @Anonymous authentication on IIS?

    2. Do you put the section :

    on web.config of the WCF service?

    Any help would be appreciated

Leave a comment