Custom Username and Password Authentication in WCF 3.5

A few days ago I wrote about a new feature in WCF 3.5 to detect client's IP address. The other new feature in .NET Framework 3.5 and Windows Communication Foundation 3.5 is the ability to write custom username and password validators in transport level over HTTP.

You probably know that in WCF 3.0 you had three options to use Windows authentication, ASP.NET Membership provider authentication and custom validator authentication in message level to authenticate users. Having the capability to write custom validators in transport level has been a request for developers and the reason seems to be obvious in my opinion!

Fortunately in WCF 3.5 this feature has been added and is easy to use for everyone.

In WCF 3.5 you can write your own username and password validator just by deriving from UserNamePasswordValidator base class available in System.IdentityModel.Selectors and overriding its Validate method.

In the below code I implement my own validator by deriving from UserNamePasswordValidator class and override its Validate method. Here I just write an insecure implementation to show the concepts. There is only one point to mention and that is throwing the SecurityTokenException type when authentication fails.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IdentityModel.Selectors;

using System.IdentityModel.Tokens;

using System.ServiceModel;

 

namespace CustomValidator

{

    public class MyCustomValidator : UserNamePasswordValidator

    {

        public override void Validate(string userName, string password)

        {

            // This isn't secure, though!

            if ((userName != "Keyvan") || (password != "testPa$$word"))

            {

                throw new SecurityTokenException("Validation Failed!");

            }

        }

    }

}

Once you write your own custom implementation for the validator, you're able to configure your service to user it.

You can use two different security mechanisms to apply this validator. You can use a message security over transport or transport level security.

So configurations for a service to apply above custom validator should look like this:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.web>

    <compilation debug="true" />

  </system.web>

  <system.serviceModel>

    <services>

      <!-- Other elements are removed -->

 

      <bindings>

        <wsHttpBinding>

          <binding name="CustomAuthentication">

            <security mode="Transport">

              <transport clientCredentialType="Basic" />

            </security>

          </binding>

        </wsHttpBinding>

      </bindings>

 

      <behaviors>

        <serviceBehaviors>

          <behavior name="CustomValidator.ServiceBehavior">

            <serviceCredentials>

              <userNameAuthentication

              userNamePasswordValidationMode="Custom"

              customUserNamePasswordValidatorType="CustomValidator.MyCustomValidator, CustomValidator"/>

            </serviceCredentials>

          </behavior>

        </serviceBehaviors>

      </behaviors>

    </system.serviceModel>

</configuration>

You see that I used a wsHttpBinding binding and applied a transport level security with Basic credential type. Then I configured my behavior with a <userNameAuthentication /> element that has its userNamePasswordValidationMode attribute set to Custom and its customUserNamePasswordValidatorType attribute set to the type of the custom validator that I implemented before.

I personally found this new feature very helpful because usually I don't use ASP.NET membership provider for a WCF application and Windows authentication isn't appropriate for many situations.

[advertisement] Axosoft OnTime 2008 is four developer tools in one: bug tracking, project wiki, feature management, and help desk. It manages your development process so developers can focus on coding. Installed or Hosted – Free Single-user license -- Free 30-day team trial.

13 Comments : 02.02.08

Feedbacks

 avatar
#1
Pasupathi
02.03.2008 @ 10:25 PM

The article looks simple and good. It would be good if you could add few lines to show how a client can pass this credentials to communicate to the service...

 avatar
#2
Harendra
02.08.2008 @ 9:31 AM

This feature is avlb in WCF 3.0 as well, it's not specific too WCF 3.5.

If you are using 'Message Mode' Security with clientCredentialType of 'UserName' then you could use code as per below:

client.ClientCredentials.UserName.UserName = @"HKumar";

client.ClientCredentials.UserName.Password = "password";

I have not tried using transport security with custom validator so won't be able to help yet (may bbe in few days !!)

admin avatar
#3
Keyvan Nayyeri
02.08.2008 @ 9:33 AM

@Harendra:

Did you read the post carefully?!

 avatar
#4
Emanuel Neto
02.11.2008 @ 6:21 AM

Hello.

I read your article I still I am confused...

I'm form Portugal and I am starting on .net framework 3.5 development.

Since you are experienced in .net security services, from what I read, I would like to ask you for an advise.

Demand:

My project requisits demand the most abstraction level uppon all layers of project. This means than in the future I should be able to make managment over my authentication method, validation and rules if I like.

Reading:

I read about authentication encapsulated on the header of each xaml message, using a factory. Other factories services could be use depending on tokens, using cardspace. An alternative is using remote services for iis validation either over tcp or https or even over simple http. (What a confusion for a beginner like me)

Goal:

My goal is to implement the most recent technology available. The most Abstration level between any layer would be necessary, since I would be using different clients and services. Form what I could guess, in the future, I would need to define roles, different profiles according to LAN or WAN users, etc. Preferable use of .net3.5

Question:

What are the basics to build this class?

What other classes do I need to create to cooperate with them and with what purpose?

Dificulty:

I still cannot see the picture of the possible architecture diagram for this build. I will start form the basic. I'm not asking you to write me code. I'm hopping that your experience could see it more clear and tell me what to do or help me to decide.

Well, I hope I can help you somehow in the near future. I (we - 8 developers team) are available to commit to you any help you find usefull. (we are all starting .net3.5 and building new project integrating WCF, WPF, WF, and frameworkservices. In the future we will use cardspace as well.)

Sincerelly,

Emanuel

 avatar
#5
Michael Giagnocavo
02.14.2008 @ 10:49 PM

Hey there, thanks for this good intro article. I was wondering, can you share the rest of your web.config and IIS configuration? I can't get IIS to accept this, it complains with all sorts of errors...

 avatar
#6
Dan
02.24.2008 @ 3:39 PM

Hi,

Thanks for the article. I have got this working now, and my service methods are callable from the client using this method of security. I was wondering if you knew how to retrieve the username from within my service's methods? I need to know who is calling my method to apply authorisation etc. I have looked all over and cannot find any pointers - any help would be much appreciated!

Thanks,

Dan

Thanks for

 avatar
#7
Mike
02.27.2008 @ 8:52 AM

I too would appreciate it if you could include the entire web.config for using the custom validator. I am unable to edit the config file from your original application and get anything to work.

Thanks

 avatar
#8
G
04.28.2008 @ 9:21 AM

driving = deriving?

admin avatar
#9
Keyvan Nayyeri
04.28.2008 @ 9:22 AM

@G:

Yes, a missing "e" ;-)

 avatar
#10
infocyde
09.05.2008 @ 10:10 AM

Thanks for posting, this was exactly what I needed!

 avatar
#11
Shaun
10.03.2008 @ 1:48 PM

Thanks for this. I'm running self hosting and don't want to use a service certificate and wondering how I can get around using the HTTPS, but still have service authentication for wsHTTP binding.

With basicHTTP I was able to set security to TransportCredentialsOnly, but wsHTTP doesn't have this option.

Thanks

 avatar
#12
Leonardo Lima
11.11.2008 @ 3:33 PM

Hi, I´m starting with WCF, and your post is what I need, but I´m understanding all right, I´m confuse, if I need put this, into CLIENT web.config, or SERVER web.config, or BOTH.

Can you clear my mind ?!

 avatar
#13
forsyte
12.08.2008 @ 7:11 PM

Hi!

I think it can not work over HTTP. Because in System.ServiceModel method GetTransport() always return for <security mode="Transport"> HttpsTransport. Here this method

protected override TransportBindingElement GetTransport()

{

if ((this.security.Mode == SecurityMode.None) || (this.security.Mode == SecurityMode.Message))

{

return base.HttpTransport;

}

this.security.ApplyTransportSecurity(base.HttpsTransport);

return base.HttpsTransport;

}

Leave a Comment