Silverlight, ASP .NET, C#, AJAX, and all things Web 2.0

dinsdag 3 februari 2009

Username Authentication with Silverlight, WCF & basicHttpBinding

When talking about security for service calls, there are actually a few things to consider.  First of all, how do you make sure the data sent over the wire is encrypted?  That's your first level of security: always make sure the data that's being sent over the wire is encrypted.  After all, unless we're working in an intranet environment, anyone could potentially look at the packets that are being sent. 

Luckily, securing this is easy to do: use SSL/https.  As far as SL/WCF is concerned, this comes down to setting your security mode to "Transport" in your binding.  That's really all there is to it.

On to the next level, what this is all about: securing your calls (for reference, I've made a Visual Studio solution documenting different ways of doing this - you can download that at the bottom of this post).  Lots of projects have some kind of requirement stating only certain people can call certain service operations - for example, you might only want people with a valid username/pw-combination to be able to call your operations, instead of letting everyone call them.  Seeing your servicehost will probably be publicly available (again, unless you're working in an intranet-environment),  anyone could potentially write a client to communicate with your services.  This obviously poses some serious risks.

So, on to username authentication on your service operations.  The idea is that you will require every service call to provide you with a username/pw-combination.  In the service operation, this combination will be validated and  the call will only continue if the combination is valid.  Thus blocking off everyone who hasn't got a valid  combination from using your services! Since we're using SSL/https to encrypt our message, we can safely send the username/pw over the wire.  A comparable method already exists out of the box with WsHttpBinding, but in  Silverlight, we're limited to basicHttpBinding, so we can't use that one.

This project shows different ways of implementing this:

  • No authentication.  This is a regular service call, everyone will be able to call the service, no username/pw is passed or sent over the wire, no authentication is done.  This is, obviously, not secure, and shouldn't be done outside of a controlled environment.
  • Authentication through method parameters. Username/pw are provided via parameters to the service method. Authentication is done in the service method.  This will work, but it isn't exactly a beautiful solution: all your service method signatures will have to have 2 additional parameters: username & pw.
  • Authentication through message headers. Instead of passing the username/pw to the method via parameters, they are passed by adding them to the message header of the message which is sent over the wire. Once in the service method, they are extracted and authentication is done.  This is already a lot better than the previous method: no additional parameters are required.
  • Authentication through message headers by implementing an operation behavior. Same as the previous method, but instead of writing code in every method to check username/pw, we write this code once in a custom operation behavior. Every method decorated with this attribute will automatically perform username/pw authentication. This is the preferred way to implement username/pw authentication.

Conclusion: nice code, not too much clutter, encrypted messages & safe calls! :-)
For those of you who want to read more about this (and then some), I got A LOT of help from the reference made by David Betz - give it a read if you find the time.

As usual, full source code is included.  You can download that here.  Enjoy!