Web Services Security
20.04.2007
Why does every article I read (here's the most recent) on this subject lately advocate using custom SOAP headers to transmit user credentials for web services? I just don't get it. With the current state of affairs with web service security, you have 2 choices; you can use transport authentication (i.e. HTTP authentication mechanisms), or you can roll your own. Until WS-Security or SAML becomes a widely adopted reality (read: supported by multiple toolkits), this is pretty much it. Let's analyze this choice in a bit more detail.
HTTP Security
For public web services, we can use Basic, Digest, or a certificate-based scheme. The first thing we should get straight here is that you don't necessarily have to let IIS authenticate against your Windows Active Directory for these mechanisms to work; you can implement the authentication mechanism yourself, and use any credential store you like. I've written this code both in an unmanaged ISAPI filter, and in managed .NET HTTP Module code; it's certainly possible.
Basic is easy to implement, requires only one round trip, but carries with it the requirement to encrypt every call since the credentials are sent in essentially clear text (actually base-64 encoded). The big win here is that just about every web service client can work with Basic.
Digest is a little tougher to implement, but can still be done in a single round trip after the initial authentication. Passwords are no longer sent clear text (they are used to generate a hash), so this mechanism does not necessarily require transport encryption. Not as many clients understand this, but the client side is pretty easy to implement. Interestingly, Microsoft chose Digest authentication for their MapPoint.NET service.
The big win to using one of these methods is that there is a good chance that a client will understand how to authenticate with your web service without having to study your API and write special code to authenticate with your service. This is what standards are for, no?
Custom Security
I've seen 2 mechanisms for this proposed in many places, and I don't like either one of them. In particular:
SOAP header carries credentials
Well, a good idea in principle. After all, this is essentially what WS-Security is doing (more or less). It allows you transport independence and it allows you to encrypt or hash credentials without necessarily encrypting your whole message. The problem is that no one understands your API without reading the documentation, and then they have to carefully construct your custom SOAP headers by hand. Why not use Digest authentication until WS-Security is implemented by a critical mass of clients? Simpler, well-documented, and several SOAP toolkits already implement it out of the box.
Login method
The idea here is that you call a login method on the web service with your credentials, and you're passed back a token which you send with every call, perhaps in a custom SOAP header. Yuck. I can think of lots of reasons not to like this one: a) it's not self documenting; b) it requires a minimum of 2 round trips for any single web service call (3 if a logout method exists to clean up the session); c) implies a sessioned model on the services, which in many cases map better to a sessionless model. And what really gets me is this mechanism is usually justified with an argument like "this way you don't have to authenticate every call" - well, in the real world, it is typically about as expensive to validate that a security session token is indeed valid and extract the information from it, as it is to just re-authenticate. Unless your authentication is incredibly expensive, I just don't buy this argument.
Related information
