Scott Watermasysk asks how he should deal with password validation for UsernameTokens with WS-Security if he has stored his passwords salted and hashed. This is something I’ve had some discussions about recently with people in the web services product team.
Fundamentally there is no silver bullet that answers this question. The hashed option for the UsernameToken does rely on the same key/password being available on both the client and server in the same form (i.e. usually the plain text of the password). Various people have suggested an approach that works within these constraints and that improves things a little. What this amounts to is storing something on the server that at least means the user’s original plain password isn’t available: if the password store is compromised for this application, the same password used on other systems is still safe. However, it does mean that compromising this password store is as good as having the plain text password as far as this application goes.
What you choose to do in this situation depends on what level of security you are comfortable with and the environment that your application is operating in. There are a number of options:
- In an enterprise application, you might be able to deploy PKI machine certificates with your client application. This gives you the opportunity to encrypt message including the UsernameToken and so the password can be sent without hashing.
- Over the Internet in a point-to-point infrastructure, you might choose to deploy the web service using SSL (HTTPS). Again this allows the password to be sent in the clear within the UsernameToken because the transport layer will take care of the encryption. This is non-ideal if you want to apply routing to the SOAP messages but might be an acceptable compromise.
- In a corporate environment you might be able to use Kerberos instead of UsernameTokens.
- You might choose to store the passwords with reversible encryption instead of salt/hash. This protects passwords from casual browsing of the password store but enables you to retrieve the original password and use the hashed option to UsernameToken.
- You might use an approach like Keith Brown’s (linked above) and require manipulation of the password on the client before it is sent hashed.
I’m sure there are other alternatives too. How have you solved this problem?