Recently, I’ve been helping a customer with some Web Service issues. One of the problems was their limited knowledge of security in that area. He asked me to explain, in Jip and Janneke language [1] how SSL works and what it actually secures.
There seems to be a lot of misunderstanding about Web Service security. Using password authentication doesn’t prevent unauthorized users to access your services, while SSL / HTTPS doesn’t give you any information about who is trying to access your services. And did you ever think of signing you messages with a digital signature?
In my introductory post I’ve elaborated on what type of security we’d typically want on Web Services.
This article will go more in-depth in the Username Token authentication.
First, I’ll list the 5 security requirements we usually have to feel really secured. These have been treated in the introductory post in this series.
-
The client must be sure it sends it messages to the correct provider;
-
The provider wants to be sure that the client is authorized to;
-
The provider wants to be sure that the client is who it says it is;
-
Both the consumer and provider want to be sure that the messages can only be interpreted by eachother;
-
Both parties want to be sure that the message sent is received unchanged.
The username token will take care of items 2 and 3. The username token is typically a security header in the soap message from the client towards the server. This header contains a username and a password, in one form or another.
In the simplest form, a UsernameToken authentication header contains an element with a username and one with a password. This is the “PasswordText” option of the UsernameToken. When you send this message unencrypted, anyone would be able to read your username and password, an log in on your behalf. Encrypting the communication will solve this risk. However, if the message has to pass several endpoints and one of the connections in unencrypted, your password is open again, despite effort to secure it.
To prevent giving away the username and password combination for free, it is possible to use the “PasswordDigest” version of the UsernameToken. This will actually pass a hash of your password, instead of the password itself. This prevents malicious ears from plucking you password off the wire.
However, although the password is encrypted and unknown to any third party, that third party could log log in by copying the entire security header. After all, if one client can get in using that header, any client could. To prevent this, a Nonce and/or a Timestamp are made part of the hash too. The Nonce is a random value, chosen by the client. The Timestamp is the date and time the password was hashed.
So how does this prevent another user from replicating your authentication header? Well, if a Timestamp is used, the server could require that that timestamp may not be older than for example 5 minutes. This still gives the third party a 5 minute window to abuse your password. That’s where the Nonce comes in. The server can (and should) require that the Nonce may be used at most one time. If the same header -and thus the same nonce- is sent again, the UsernameToken is refused based on a duplicate nonce.
In the end, the security header could look like this:
<wsse:Security xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd” SOAP-ENV:mustUnderstand=”1″> <wsse:UsernameToken xmlns:wsu=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd” wsu:Id=”UsernameToken-33083972″ xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”> <wsse:Username xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”>username</wsse:username> <wsse:Password Type=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest” xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”>Zb5nkZdaXM3hH/bVPQRdMdYSbdo=</wsse:password> <wsse:Nonce xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”>hHDHOSh3akTwwZFs+6o13A==</wsse:nonce> <wsu:Created xmlns:wsu=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd”>2008-05-20T19:00:06.937Z</wsu:created> </wsse:UsernameToken> </wsse:Security>
So, does this make us absolutely secured from any attacks? Well, the likelyhood of anyone abusing your security header is very slim, but nowhere near to zero. Hackers keep lists of commonly used passwords and can use these lists to guess your password. They will see which passwords will create the given hash using the Nonce and Timestamp you have provided. It is therefore very important to generate a password instead of choosing one which is easy to remember. Why would you anyway, a client is usually a piece of software that doesn’t really have difficulties remembering any password. It is of course still not water tight, but it is more likely that the service won’t exist anymore by the time the password has been guessed.
Another way to minimize the chance of abuse of your credentials is by encrypting the messages, or parts of it. This shall be treated in my next post in this series.
The configuration of UsernameToken security in your WebService is fairly simple. Both in client and server only little configuration is needed. There are libraries that can assist you in setting up security, such as Apache’s WSS4J and Sun’s XWSS. If you want to see these libraries at work, make sure you download the code samples for this series on the Gridshore code repository: http://code.google.com/p/gridshore/source/checkout [1].
If you want to go into a little (or a lot) more technical depth of the UsernameToken specification, make sure you read the OASIS WSS specification from http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss#technical.
This concludes this post about the UsernameToken. In my next post in this series, I will shed some light on Transport Level Security and Message Encryption.
[1] Make sure you checkout the code in the /trunk/feeling-secure-with-webservices/ folder. If you check out the entire trunk, you’ll have to deal with lots of samples.