Keyvan Nayyeri

God breathing through me

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.

25 Comments

Pasupathi
Feb 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...


Harendra
Feb 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 !!)


Keyvan Nayyeri
Feb 08, 2008 9:33 AM
#

@Harendra:

Did you read the post carefully?!


Emanuel Neto
Feb 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


Michael Giagnocavo
Feb 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...


Dan
Feb 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


Mike
Feb 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


G
Apr 28, 2008 9:21 AM
#

driving = deriving?


Keyvan Nayyeri
Apr 28, 2008 9:22 AM
#

@G:

Yes, a missing "e" ;-)


infocyde
Sep 05, 2008 10:10 AM
#

Thanks for posting, this was exactly what I needed!


Shaun
Oct 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


Leonardo Lima
Nov 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 ?!


forsyte
Dec 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;

}


arne
Jan 12, 2009 9:56 AM
#

I have read you article about CustomUsernameAndPassword validation and the article about getting the Client ip address. This is also how we do it. The problem is that you can not combine the two. You can not get the clients IP address when using custom validation cause the statement OperationContext context = OperationContext.Current; will always yield null as a result (at least to my knowledge).

Do you have a way to get the clients IP address in the overridden validate method?

Arne


Keyvan Nayyeri
Jan 12, 2009 10:02 AM
#

@arne

I'm not 100% sure but you may be able to extract that info by using web context rather than operation context. You may also want to try using ASP.NET hosting evironment to extract the IP (if your business scneario allows).

In the worst case you should be able to implement a custom listener to extract the IP address.


Steve
Feb 09, 2009 1:51 PM
#

Hi,

I was following your example. However the code was not responding to the custom password settings. I tried attaching to the w3xp.exe and set a break point on the custom validator code. But the password code is not being hit. Is there anything you can think of that might lead to this behavior.

Steve


Sattty
Mar 21, 2009 1:14 AM
#

Hi keyvan...

I just Saw your article on Custom Username and Password Authentication in WCF 3.5 ,the article looks simple and nice.So, i tried to implement it in my local project ..As i m beginner and have very little knowlege abt WCF , Kindly could please tell me how can client pass credentials to communicate to the service... ...Thanks.. help needed urgently ...


Frank
Mar 26, 2009 4:14 PM
#

Do you know how to grab this user id later in my services for authorization or for audio purpose?


Vladimir
Apr 29, 2009 7:01 PM
#

Hi,

it seems to me that UserNamePasswordValidator doesnt work with transport security mode, only with message security mode where clientCredentialType="UserName"

example could be found here:

msdn.microsoft.com/.../aa354513.aspx


Thiyagarajan N
May 19, 2009 1:10 PM
#

Hi,

good article. I did the same. but i got the below error..

"Secure channel cannot be opened because security negotiation with the remote endpoint has failed. This may be due to absent or incorrectly specified EndpointIdentity in the EndpointAddress used to create the channel. Please verify the EndpointIdentity specified or implied by the EndpointAddress correctly identifies the remote endpoint."

How can I rectify this?

Thanks

Thiyagarjan N


DR
Jun 30, 2009 12:35 AM
#

Hi Do you have any example on customizing membership provider using own table and using Linq?Anyone got idea?


ara
Oct 13, 2009 2:53 AM
#
thanks alot for your article, im learning wcf right now and i wonder how would i test this code?i've already built them on my pc and try using wcftestclient.exe, but i could not see whether it runs or not

bp
Dec 15, 2009 10:54 PM
#
how in the heck do you test security in VS 2008 on localhost? WCF is a mess!

Dilbagh Singh
Dec 17, 2009 5:23 AM
#
hi,

good artical. i have implement this in my service.
but i got the following error:
Could not find a base address that matches scheme https for the endpoint with binding WSHttpBinding. Registered base address schemes are [http].

pleasee give ur commnets on this error.

thanks in advance

VM
Dec 28, 2009 9:18 AM
#
@Dilbagh Singh

I am facing the same error "Could not find a base address that matches scheme https for the endpoint with binding WSHttpBinding. Registered base address schemes are [http]."

Did you find any solution / work around?

Leave a Comment





Ads Powered by Lake Quincy Media Network