WCF – TCP with UserNameToken without Message Security

November 7, 2010

tags: ,
4 comments

There was a project that I assisted with the WCF communications where they needed to allow the client to specify different credentials without being dependent on the windows account.

The first thing that comes into mind is to use the UserNameToken technique to pass in the client credentials. The design instructed to use TCP as the transport and not use message security. Obviously, this technique has privacy and integrity issues where there isn’t any encryption nor signing, but that was their decision because it wasn’t an issue in the purpose of the project.

Well, this setting isn’t as trivial as you would expect.
The default form of the NetTcpBinding allows you to use UserNameToken only as part of message security and forces you to use a certificate to enable that message security.

I ended up setting them a CustomBinding which provides the scenario they needed.

Service Side

Configuring the Service Host –

Code Snippet
  1. _host = new ServiceHost(typeof(Service));
  2. _host.AddServiceEndpoint(typeof(IService), Config.ServiceBinding, Config.ServiceAddress.Uri.AbsoluteUri);
  3.  
  4. _host.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
  5. _host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameTokenValidator();
  6.  
  7. _host.Open();

Custom Simple Validator (you can write any logic you need here) –

Code Snippet
  1. class CustomUserNameTokenValidator : UserNamePasswordValidator
  2. {
  3.     public override void Validate(string userName, string password)
  4.     {
  5.         Console.WriteLine("CustomUserNameTokenValidator.Validate – {0} / {1}", userName, password);
  6.  
  7.         if (string.IsNullOrEmpty(userName))
  8.         {
  9.             throw new SecurityTokenValidationException("Invalid username");
  10.         }
  11.     }
  12. }

In the service code, you can extract the caller’s identity name as follows –

Code Snippet
  1. class Service : IService
  2. {
  3.     public void Do()
  4.     {
  5.         Console.WriteLine("Service.Do() – Identity Name: {0}",
  6.             ServiceSecurityContext.Current.PrimaryIdentity.Name);
  7.     }
  8. }

Client Side

In the client side you need to use the same binding, provide the UserNameToken credentials and simply call the service –

Code Snippet
  1. ChannelFactory<IService> factory = new ChannelFactory<IService>(Config.ServiceBinding, Config.ServiceAddress);
  2. factory.Credentials.UserName.UserName = "myUser";
  3. factory.Credentials.UserName.Password = "myPassword";
  4.  
  5. IService proxy = factory.CreateChannel();
  6.  
  7. proxy.Do();
  8.  
  9. ((ICommunicationObject)proxy).Close();

Configuration

Following is the CustomBinding which enables this scenario –

Code Snippet
  1. SecurityBindingElement securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
  2. ((TransportSecurityBindingElement)securityElement).AllowInsecureTransport = true;
  3.  
  4. _serviceBinding = new CustomBinding(new BindingElement[] {
  5.     securityElement,
  6.     new BinaryMessageEncodingBindingElement(),
  7.     new TcpTransportBindingElement()
  8. });

Feel free to download the source code and see that in action.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

4 comments

  1. Yaron NavehNovember 7, 2010 ב 22:07

    Customers that still use Wcf 3.5 can do the same “trick” as in ClearUsernameBinding:

    http://code.google.com/p/wcf-clear-username-binding/

    Reply
  2. Amir ZukerNovember 8, 2010 ב 7:33

    Thanks for pointing that out Yaron.
    Seems a bit overshoot in this case though, since you can do it using plain vanilla WCF as in the example.

    Amir Zuker

    Reply
  3. Yaron NavehNovember 8, 2010 ב 12:10

    Amir – this is only available from .Net 4.0. In .Net 3.5 this was not available. There was a hotfix over .Net 3.5 SP1 which added this capability but it had a few problems.

    Reply
  4. Amir ZukerNovember 8, 2010 ב 13:18

    Thanks for clearing that out Yaron.

    Reply