Sunday, January 31, 2010

Username authentication in WCF

Imagine following requirements:

  • You want to send data to a WCF service in a secure way
  • To maximize compatibility you have to use basic HttpBinding
  • You want to authenticate using a username/password combination

In WCF the only option you have based on these requirements is the use of SSL.

On server side you have to configure your service using the TransportWithMessageCredential security mode. Configure your binding as specified below:

   1:  <bindings>
   2:        <basicHttpBinding>
   3:          <binding name=”SecureHttps>
   4:            <security mode=”TransportWithMessageCredential>
   5:              <message clientCredentialType=”UserName/>
   6:            </security>
   7:          </binding>
   8:        </basicHttpBinding>
   9:  </bindings>

Verification of the client credentials can be done using for example the ASP.NET membership provider or you can specify your own custom authenticator.

   1:  <serviceCredentials>
   2:              <userNameAuthentication userNamePasswordValidationMode=”Custom
   3:                customUserNamePasswordValidatorType="Services.CustomUserNamePasswordValidator, Services/>
   4:  </serviceCredentials>

Create then the following class:

   2:  public class CustomUsernamePasswordValidator : UserNamePasswordValidator 
   3:  {
   4:          public override void Validate(string userName, string password)
   5:          {
   6:              //your validation here
   7:          }
   8:  }

And if you are using the generated proxy on the client side, the only remaining thing you have to do is specifying some client credentials:

   1:  using(var serviceProxy=new SecureService())
   2:  {
   3:        serviceProxy.ClientCredentials.UserName.UserName="Test";
   4:        serviceProxy.ClientCredentials.UserName.Password="Test";
   5:       //Call service operation
   6:  }


Robert Bell said...

Is this for WCF 4.0? I tried it and my CustomUsernamePasswordValidator is not firing.

Bart Wullems said...

I tested it both in WCF 3.0 and 4.0. Did you doublecheck that you didn't made any typo's?