Featured Post

Watch 1400 80′s Videos!

For anyone that knows me, you know my musical taste lies in the 80′s. Call it what you will, the 80′s still rock. Nothing gets me coding in the morning like a good dance hit from the 80′s. I found a web site that allows you to watch over 1400 80′s vidoes! You remember videos right?...

Read More


Securing Web Services With Username and Password

Posted by Keith Elder | Posted in .Net, Asp.Net, Programming | Posted on 06-01-2007

I was going through my news feeds this morning and stumbled across this article about securing web services.  The article is short and doesn’t give any examples of one of the methods I use a lot.  I thought I would elaborate on one of the topics it touches on which is securing a web service with a Username and a Password.  While there are other ways to secure web services I find this particular method works really well when dealing with internal systems that may not speak .Net.  It is also simple to implement on both sides.  These systems could be in Java, PHP or even 4GL.  If you are a .Net developer and want to secure a web service with a username, password, or even other information, here is what you need to get going.

1.  Create an object that extends SoapHeader

The first thing you need to do is create an object that extends the built-in SoapHeader object.   The object can be simple or complex. Add the tokens you want to authenticate against.  Here is a sample:

    1 /// <summary>

    2 /// Extends from SoapHeader and provides a username / password

    3 /// for web methods that need authentication.

    4 /// </summary>

    5 public class ServiceAuthHeader : SoapHeader

    6 {

    7     public string Username;

    8     public string Password;

    9 }

2.  Add a property to your service class that uses the class above

Once you’ve created your base soap header class, add it as a property to your service class.

    // SoapHeader for authentication

    public ServiceAuthHeader CustomSoapHeader;

3.  Attribute the method you want to secure

Add the SoapHeader attribute to each or certain methods you wish to secure pass in the name of the property that is defined as the SoapHeader object in step 2.

    1     [WebMethod]

    2     [SoapHeader("CustomSoapHeader")]

    3     public int AddTwoNumbers(int x, int y)

    4     {

    5        

    6         return x + y;

    7     }

4.  Create a method to process your SoapHeader for authentication

The last big step is to create a static method that will take in your custom soap header class and process it for validation.  The first thing we want to do is make sure that some type of credentials were passed in the SoapHeader and that the properties we are looking for are not null.  Finally we want to validate each property contains the information we are looking for. This could be read from the web.config file, database, or other places.

 

    1 public class ServiceAuthHeaderValidation

    2 {

    3     /// <summary>

    4     /// Validates the credentials of the soap header.

    5     /// </summary>

    6     /// <returns></returns>

    7     public static bool Validate(ServiceAuthHeader soapHeader)

    8     {

    9         if (soapHeader == null)

   10         {

   11             throw new NullReferenceException(“No soap header was specified.”);

   12         }

   13         if (soapHeader.Username == null)

   14         {

   15             throw new NullReferenceException(“Username was not supplied for authentication in SoapHeader.”);

   16         }

   17         if (soapHeader.Password == null)

   18         {

   19             throw new NullReferenceException(“Password was not supplied for authentication in SoapHeader.”);

   20         }

   21 

   22         if (soapHeader.Username != “myusername” || soapHeader.Password != “mypassword”)

   23         {

   24             throw new Exception(“Please pass the proper username and password for this service.”);

   25         }

   26         return true;

   27     }

   28 }

5.  Add validation to service method

 

    1     [WebMethod]

    2     [SoapHeader("CustomSoapHeader")]

    3     public int AddTwoNumbers(int x, int y)

    4     {

    5         // Test to see if the proper credentials were passed in.

    6         ServiceAuthHeaderValidation.Validate(CustomSoapHeader);

    7 

    8         // If we get this far the user has been validated.

    9         return x + y;

   10     }

 

That’s it. You now have all the pieces of the puzzle to process a request and validate the credentials of the calling client via a username and or password.  If we launch the solution we will see that our XML for our service has been updated and now contains an XML Node called ServiceAuthHeader which contains two sub nodes: username, password.

Passing SoapHeader Credentials To Your Service

Now that we have our service secured, we need to now call the service and pass the credentials expected from a client.  Based on the example above, once you add a web reference to the service and instantiate the service in code, the thing you want to look for is a new property of your service proxy called ServiceAuthHeader. This is converted into a property called ServiceAuthHeaderValue.  This property needs to be an instantiation of the ServiceAuthHeader class where you set the username and password properties.  Here is an example of a console application calling our service and passing the required information to authenticate.

    1 using System;

    2 using System.Collections.Generic;

    3 using System.Text;

    4 

    5 namespace ConsoleApplication1

    6 {

    7     class Program

    8     {

    9         static void Main(string[] args)

   10         {

   11             localhost.Service service = new ConsoleApplication1.localhost.Service();

   12             localhost.ServiceAuthHeader header = new ConsoleApplication1.localhost.ServiceAuthHeader();

   13             header.Username = “myusername”;

   14             header.Password = “mypassword”;

   15             service.ServiceAuthHeaderValue = header;

   16             int x = service.AddTwoNumbers(1, 1);

   17             Console.WriteLine(x);

   18             Console.ReadLine();

   19         }

   20     }

   21 }

 The return result will be 2 of course and from the client side it is rather trivial to pass the credentials as you see.   That’s it.   Happy authenticating!

[Related Link]
To take authenticating one step further with a custom SoapExtension read this follow up article.
http://keithelder.net/blog/archive/2007/01/09/Take-Securing-Web-Services-With-Username-and-Password-One-Step.aspx

 

  • Mohamed Rafeeque

    Adding SoapHeader Provides More security.Can you Give me the reply that whats is the difference between checking a parameter from webservice

    ex:

    i havea webmethod

    [WebMethode]

    public intAuthenticte(int a ,int b,int check)

    {

    int c;

    if(check==”1234″)

    {

    c=a+b;

    }
    return c;
    }

    is this same as that of adding SoapHeader security.kindly reply me

  • http://www.register-web-domain.in/ Domain registration

    Wonderful Reading I must say that this is a great post.Thanks

  • http://www.register-web-domain.in Domain register

    Nice reading thank you for sharing this great info.i well comeback for further articles

  • http://www.webhostings.in/ Hosting India

    Valuable information and excellent design you got here! I would like to thank you for sharing your thoughts into the stuff you post!! Thumbs up!

  • http://www.webhostings.in/ hosting server

    Very useful articles will definitely share it to others Thanks to sharing

  • D00m

    How to access to this kind of web service from java?

  • D00m

    How

  • Anonymous

    Thank you so much Keith! It is nice to find succinct examples of what I need, this is one of them :)

  • Anonymous

    Thanks for this fantastic article. It’s the exact solution I was trying to figure out. 8-)

  • http://keithelder.net/blog/Default.aspx Anonymous

    Hi Michael,

    While passing in a username / passowrd to a function marked with the [WebMethod] attribute would work it is not the optimal choice. For starters when writing services, you should avoid passing parameters, instead think in “messages”. A message is just an object. It is the pay load.

    As an abstraction to that message, the header can contain other data such as security, routing, session state, cookies, etc. By having this stuff in the header you can easily abstract out the adding of this into your calls so that you don’t even have to think about it, not to mentioning sprinking a username / password all over the place for each call. I can’t image even doing that.

    As far as WCF vs ASMX, see this post I wrote awhile back on the two:

    http://www.keithelder.net/…/…vs-ASMX-WebServices.aspx

    And then watch this video I did for MSDN that is on Channel 9. I show you point blank that WCF is faster and offers way more advantages than ASMX. The solution is in the post as well.

    keithelder.net/…/…-strategies-on-channel9.aspx

  • Anonymous

    Great post Elder!

    I have two questions as I try to get up to speed on this:

    somewhere on this thread, you mention that the name and password will be secured by ssl. If that is so, why not just pass them across as variables to the webmethod. Are those not secured?

    Also, on the thread you mention that new web services should be written in wcf. I understand that this is the new super set of all of microsoft’s past service technologies, but what advantage does it have over asmx if you are just trying to pass soap messages? And how can you set a soap header in wcf?

    Thanks!

  • Anonymous

    How would you connect to a secured web service like this using the ms soap toolkit in vb6? is it possible?

  • Anonymous

    Thanx, u made my life easier! Great example!!!

  • http://www.serigranit.com/ Anonymous

    Thank You…

  • http://keithelder.net/blog/Default.aspx Anonymous

    @Chris

    Not to my knowledge. The way XML serialization works is Username and Password would have to be a property of the Soap Header itself. All we are doing is inheriting from SoapHeader to create another serialized object.

    Nothing comes to my mind as to how you’d achieve that, but I haven’t tried to explore it either, just using prior knowledge.

  • Anonymous

    Keith,

    What about if I don’t want to see the class ServiceAuthHeader? Can you make you data look like..

    <soap:Header
    <Username>string</Username>
    <Password>string</Password>
    </soap:Header>

    By using the ServiceAuthHeader class?

    Thanks,
    Chris

  • Anonymous

    Keith,

    What about if I don’t want to see the class ServiceAuthHeader? Can you make you data look like..


    string
    string

    With the ServiceAuthHeader class?

    Thanks,
    Chris

  • Anonymous

    @Balakathiresan:

    Please check “Service header” when you call service

  • http://www.vibrant.in/ Anonymous

    Hi Keithe ur Article is very nice to help me. Then i try to do ur Securing Web Services With Username and Password coding but that time showing this error

    System.NullReferenceException: No soap header was specified.
    at ServiceAuthHeaderValidation.Validate(ServiceAuthHeader soapHeader) in e:\WebservicesecurityWSecurity\App_Code\ServiceAuthHeaderValidation.cs:line 25
    at Service.AddTwoNumbers(Int32 x, Int32 y) in e:\WebservicesecurityWSecurity\App_Code\Service.cs:line 29

    soapHeader only comming Null value .. i dont know why its comming
    so pls help me…

  • http://www.vibrant.in/ Anonymous

    i am beginer in .net webservice so I need webservice concepts all then remoting also.

  • http://www.llede.net/ Anonymous

    Thank you…

  • Anonymous

    thnkz Keith for ur Article it really helps me a lot . and i said again Thnkz a lot but i want to do one thing more as i m not so good in programing so need ur help

    that how to cath exception and show it on client side that will be generated by puting wrong username or password..

    if u can post any article with security and exception cathing it wil be very thknful to You,

    Any how . Thnkz a lot and great work

  • http://keithelder.net/blog/ Anonymous

    @Podi

    Keep in mind that ASMX web services shouldn’t be used anymore and should be replaced with WCF (windows communication foundation). WCF services offer a lot more features than ASMX and allow for more types of security by default.

    For example using the wsHttpBinding in WCF, the default configuration is to sign, encrypt, and sign a message. Messages travel back and forth securely without you having to do anything except configure them. I recently wrote an article on how to expose the same web service three different ways and there is a solution in this article that you can download to see what the messages look like. You can find it here.

    http://keithelder.net/blog/archive/2008/01/17/Exposing-a-WCF-Service-With-Multiple-Bindings-and-Endpoints.aspx

    As far as books I would recommend Michele Leroux Bustamante’s book on WCF. It is published by O’Reilly called Learning WCF.

    Here is a link.

    http://www.amazon.com/Learning-WCF-Hands-Michele-Bustamante/dp/0596101627

    Hope that helps you and others to understand that if you are reading this article today, you really shouldn’t be unless your client or work place will not let you move forward to the newer technologies.

    -Keith

  • Anonymous

    Keith (or any one else),

    First and foremost, thank you for the great article. These basics were exactly what I was looking to get started.

    I am a beginner in implementing .NET web services. I would like to learn more about securing web services. Do you have any books that you could refer in this subject matter?

    Thank you!

  • http://keithelder.net/blog/ Anonymous

    First off let me say that I disagree with your first comment that it introduces replay attacks. It doesn’t introduce anything. Your argument basically says any web service introduces replay attacks, at least that is how I read it. It doesn’t introduce anything that wasn’t already there.

    Secondly you assume the text is passed in clear text. Obviously I didn’t mention SSL as the transport but I would assume that you and others would understand that if you don’t secure the transport you aren’t doing yourself anygood.

  • Anonymous

    there is a fundamental flaw in your design. The methods you have explained above introduce the possibility of replay attacks thereby rendering the username and password scheme redundant. Also you method will be transmitting passwords in clear text. In short this method will not be able to defend against what you intended to protect

  • http://keithelder.net/blog/ Anonymous

    I added a new artice that shows how the custom SoapExtension is done. You can view it here:

    http://keithelder.net/blog/archive/2007/01/09/Take-Securing-Web-Services-With-Username-and-Password-One-Step.aspx

  • http://keithelder.net/blog/ Anonymous

    You could write a custom SoapExtension and attribute the method with the extension and handle validation automatically. I’m a fan of attribution. I’ll write that out and update the post.

    Not only does doing a SoapExtension provide automatic authentication, but it could also allow you to hook into a config file or database to validate each method differently dependent upon permissions.

    I’ll write that up real quick and update the article.

  • http://www.juxtaviews.com/ Anonymous

    I have WS authentication implemented just like this already and it works great, the only issue is having to place the authenticate conditional in every WS method, and in my case I actually need to do this for additional business requirements.

    But you could use a WS-Extension that validates the authentication which would essentially remove the redundant validation condition.

    Just an idea.

  • http://www.dotnetkicks.com/aspnet/Security_Net_Web_Services_With_Username_and_Password Anonymous

    You’ve been kicked (a good thing) – Trackback from DotNetKicks.com

  • http://programame.net/story/autenticando-servicios-web Anonymous

    Si has trabajado alguna vez con servicios web, sabes que cualquier persona puede &amp;quot;consumirlos&amp;quot; salvo que apliques ciertas restricciones en el servidor. He aqu&#237; una forma de restringirlo en los m&#233;todos de una forma simple. A&#241;adiendo autenticaci&#243;n en la cabecera. NOTA: El art&#237;culo est&#225; en ingl&#233;s