Welcome

You have reached the blog of Keith Elder. Thank you for visiting! Feel free to click the twitter icon to the right and follow me on twitter.

Take Securing Web Services With Username and Password One Step Further With a Custom SoapExtension

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

22

In a previous posts I showed how to secure your web services with a username and a password.  One of the readers added a comment and mentioned using an extension to provide authentication so I thought I would expand on how that is done.  If you haven’t read the previous posts do that first, then pickup with this.  And before we get started, thanks for the idea Kevin!

Have you ever wanted to intercept a web service method because you wanted to maybe log it or even as we are about to do authenticate a user?  Did you know you can intercept any incoming SoapMessage that is sent to your web service?  This is all possible because of the SoapExtension class in .Net. Not only can you intercept the incoming message but you can do it within one of four stages:

  1. AfterDeserialize
  2. AfterSerialize
  3. BeforeDeserialize
  4. BeforeSerialize

This allows us a lot of flexibility obviously.  In our example we are going to work with the AfterDeserialize stage which is after the message has been sent across the wire and serialized into a SoapMessage object.  Since we will have a full blown SoapMessage object, we can inspect the headers of the SoapMessage and take care of authentication then.  Our end goal with taking this approach is to allow us to authenticate a user with a WebMethod simply by adding an authentication attribute to the WebMethod like this highlighted in bold.

    1     [WebMethod]

    2     [SoapHeader(“CustomSoapHeader”)]

    3     [AuthenticatonSoapExtensionAttribute] (magic here)

    4     public int AddTwoNumbers(int x, int y)

    5     {

    6         return x + y;

    7     }

You’ll notice in this example we do not have to remember to call the code to authenticate the user manually as we saw in the previous article.  Instead by adding the attribute to the method it knows to call the authentication method.  To do this we need to first create a custom object that extends SoapExtensionAttribute and then another that extends SoapExtension.

Create a Custom SoapExtensionAttribute

In order to have the method call our custom SoapExtension we need to create an object that extends SoapExtensionAttribute.  It is a farily simple class with two overridden properties.  Here’s the code:

    1     [AttributeUsage(AttributeTargets.Method)]

    2     public class AuthenticatonSoapExtensionAttribute : SoapExtensionAttribute

    3     {

    4         private int _priority;

    5 

    6         public override int Priority

    7         {  

    8             get { return _priority; }

    9             set { _priority = value; }

   10         }

   11 

   12         public override Type ExtensionType

   13         {

   14             get { return typeof(AuthenticatonSoapExtension); }

   15         }

   16     }

You’ll notice about the only thing of real substance is the Extension type property which simply returns to us our custom extension.

Create a Custom SoapExtension

The last piece to pull this all together is a custom class which extends the SoapExtension class.  In this class we are going to write the code that does the actual authentication.  We are going to check for the AfterDeserialize stage and then first make sure we have a valid SoapHeader.   Once we do that we are going to call the static validation method and pass in the SoapHeader as we did above. 

    1 /// <summary>

    2     /// Custom SoapExtension that authenticates the method being called.

    3     /// </summary>

    4     public class AuthenticatonSoapExtension : SoapExtension

    5     {

    6 

    7         /// <summary>

    8         /// When overridden in a derived class, allows a SOAP extension to initialize data specific to an XML Web service method using an attribute applied to the XML Web service method at a one time performance cost.

    9         /// </summary>

   10         /// <param name=”methodInfo”></param>

   11         /// <param name=”attrib”></param>

   12         public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attrib)

   13         {

   14             return null;

   15         }

   16 

   17         /// <summary>

   18         /// When overridden in a derived class, allows a SOAP extension to initialize data specific to a class implementing an XML Web service at a one time performance cost.

   19         /// </summary>

   20         /// <param name=”WebServiceType”></param>

   21         public override object GetInitializer(Type WebServiceType)

   22         {

   23             return null;

   24         }

   25 

   26         /// <summary>

   27         /// When overridden in a derived class, allows a SOAP extension to initialize itself using the data cached in the GetInitializer method.

   28         /// </summary>

   29         /// <param name=”initializer”></param>

   30         public override void Initialize(object initializer)

   31         {

   32 

   33         }

   34 

   35         /// <summary>

   36         /// After the message is deserialized we authenticate it.

   37         /// </summary>

   38         /// <param name=”message”></param>

   39         public override void ProcessMessage(SoapMessage message)

   40         {

   41            

   42             if (message.Stage == SoapMessageStage.AfterDeserialize)

   43             {

   44                 Authenticate(message);

   45             }

   46         }

   47 

   48         public void Authenticate(SoapMessage message)

   49         {

   50             ServiceAuthHeader header = message.Headers[0] as ServiceAuthHeader;

   51             if (header != null)

   52             {

   53                 ServiceAuthHeaderValidation.Validate(header);

   54             }

   55             else

   56             {

   57                 throw new ArgumentNullException(“No ServiceAuthHeader was specified in SoapMessage.”);

   58             }

   59         }

   60     }

The method that we are really concerned with is the ProcessMessage which checks for the stage and then calls the Authenticate method.  This in turn calls our static validation method which checks for authentication.  At this point light bulbs should be going off!   Since we have a SoapMessage object do we not know which method is being called?  Yes!  Could we modify the ServiceAuthHeaderValidation to check for a database instead of hard coding things?  Yes!  Now you are starting to see where this could really go.   SoapExtensions are powerful and only limited to your imagination. 

When I Test It, It Doesn’t Work, Why?

Once you get your SoapExtension in your solution setup and press F5 to debug it within Visual Studio  it will launch a new web server on a random port and bring you to your service.  You enter the parameters and submit the form and it by passes your validation.  Why!? 

This is suppose to happen and here is why. If you go to the service invoked from VS through the browser interface it will not invoke the authentication and it isn’t suppose to either. The reason is you are not invoking the service via SOAP but rather just a standard POST from a form. Therefore, the SOAP extension is never going to fire. This should be disabled when you publish your web service to production as only SOAP messages should be allowed. If you have a case where you need to allow GET and POST calls then the method of a custom SoapExtension isn’t going to work. Go back to the previous way outlined that I talked about.

As a benefit, Visual Studio builds the form for you automatically when you press F5 and allows you to pass parameters to the web method, but it does it via POST. If you invoke the web method from a console application or a real client making a SOAP call, you have to pass in the username and password.  I actually consider this behavior a feature.  If we didn’t use the SoapExtension to secure the method, we’d be forced to pass in username and password all the time which would mean we’d have to always call the secured web method from a test client.   Speaking from experience this isn’t fun.  Of course you should have Unit Tests for each web method anyway but it is really easy to pass in the params to a web form while debugging.

I hope you find this useful and now don’t feel so daunted because your team leader asked you how you were going to authenticate web service methods via a database.  The only thing left is for you to implement your required features.  Of course, if you are on an Intranet, instead of using username and password as we did in the previous post you could at the point of Authenticate(SoapMessage message) use the user’s integrated credentials and check for various groups in Active Directory or even using Enterprise Library Security Block. 

Like this article?  Then kick it on DotNetKicks.com

Apple Announces iPhone, Who’s Going to Buy One?

Posted by Keith Elder | Posted in Computer Hardware | Posted on 09-01-2007

1

Today at Macworld Apple announced what has been discussed and speculated to death on every blog and major publication, their iPhone.  Ok, so let’s talk about who is going to buy one.  Honestly I’ll probably buy one for Ellen.  She has been wanting a new phone since her Motorola phone is showing wear and she still uses the iBook I bought her several years ago.  We also have Cingular and we are due an upgrade (although I don’t know what the upgrade price will be).  I am not happy about the lack of 3G.  How can you release a new phone and not have it 3G enabled.  I guess we’ll have to wait for iPhone 2.0. 

Besides my wife, who else will get one?  If you are planning on getting one add a comment.  Of course a lot of the MacFanBoys will be jumping on one no doubt.  But who else?   What about corporate America?  The Enterprises?  Will they give up their Blackberry’s?  I don’t think so.   Why not?  Well the iPhone only supports IMAP and POP email which allows you to only check personal email.  Basically the phone is going to be really good for personal use, but will not see adoption in the Enterprise.  A lot of companies don’t allow phones with cameras to be brought even into the work place so there is another reason.  Thankfully, I don’t work for one though.  Which means Palm with their Treo’s running Goodlink or the Blackberries are safe for now in corporate America.

However, if this device takes off then that creates demand.  With demand comes market share and with market share comes third party ad ons.  So if you are Blackberry or Goodlink and you read this start now developing a “plugin” or something for the iPhone to get it into the enterprise.  You’ll make millions.

Anyone else planning on buying one for the whopping $499 for the 4GB version or $599 for the 8GB version?

Xbox 360 IPTV Video

Posted by Keith Elder | Posted in XBOX 360 | Posted on 09-01-2007

0

The other day I posted an article about how the Xbox 360 was one upgrade away from taking over my living room.  It looks like I get my wish!  At CES an announcement was made which will provide Xbox owners the ability to watch live TV and record live TV.  Obviously someone else agreed with my post at Microsoft and they threw this together real quick.  I’m kidding of course, but this is extremely cool.  Instead of me telling you all about it just go watch the video on http://on10.net.

Key points:

  • Available holiday 07
  • Added a new option in the media section called “Television”
  • Supports picture in picture
  • Record and pause live TV

If you are familiar with Media Center the interface is going to look very familiar.  The video is about 9 minutes, enjoy.