November 02, 2003

Encryption using UsernameToken

WSE supports signing with a UsernameToken, but not encrypting with it. Since there's a key derivation mechanism it may seem a little odd that we don't support encryption with it.

Before we start, remember that the UsernameToken is mutated every time it is used in a message: the Created timestamp and the Nonce are regenerated. This is different than all the other token types in WSE and some that aren't in it (e.g. XrML and SAML). It has two implications: first, the token is not thread-safe and second it may not be possible to recover the original state of the token, and hence the key, that was used for any particular message.

Now take a common scenario: a client signs a message with a UsernameToken and encrypts the <soap:Body> using the servers X.509 certificate (not that unreasonable for a service). The server wants to sign the response with it's X.509 certificate and encrypt the <soap:Body> with the UsernameToken.

If you've examined the message format that WSE uses for encryption, you'll have seen that we like to use a <ds:KeyInfo> to identify the encrypting token. There are quite a few possibilities for clauses within the <ds:KeyInfo> to identify the token that was used, including things like <ds:KeyName> and <wsse:SecurityTokenReference> containing either a <wsse:KeyIdentifier> or a <wsse:Reference>.

For UsernameTokens, there is no obvious clause that is suitable:

  • People use the same Username with different passwords for different services and so this just isn't a practical <ds:KeyName>
  • UsernameTokens don't have <wsse:KeyIdentifier> values
  • <wsse:Reference> doesn't work unless the token is in the message, the UsernameToken doesn't have a global URI identifier that you can use directly

Now, even if one of the above did hold, the fact that UsernameTokens mutate becomes a problem - we can't be sure that the token at the client hasn't changed - another message might have been sent in between. This would lead to using the wrong key to decrypt.

Including the token in the response message is also problematic. The client will attempt to deserialize the token and authenticate it. SecurityTokenManagers in WSE do not distinguish between requests and responses and behave the same in both cases: the token manager will attempt either a password lookup or Windows authentication of the token. Password lookup doesn't make a great deal of sense at a client; Windows authentication requires a plaintext password and a secure channel - why use the UsernameToken to encrypt the response if you already have a secure channel?

For WSE 1.0 and 2.0 Tech Preview, we simply didn't identify a practical, authoritative, interoperable model. Since interoperability is one of the top priorities for WSE, we chose to hold off doing something WSE specific and get additional guidance. With the widening use of WS-Trust and WS-SecureConversation and the fact that everyone seems to like the UsernameToken as a bootstrap, we're again looking hard at this problem for the 2.0 final release.

Posted by herveyw at November 2, 2003 05:08 PM
Comments