Blog Home  Sign In RSS 2.0 Atom 1.0 CDF  

  def Softwaremaker() :
         return "William Tay", "<Challenging Conventions />"

  knownType_Serialize, about = Softwaremaker()
 

 Thursday, November 04, 2004
« Real World UsernameToken Authentication ... | Main | Bug in the new FreeTextBox implementation of dasBlog 1.6.4121.2 »

With reference to my previous posted here on Real World UsernameToken Authentication Scenarios with WSE 2.0

I have received some very good responses and feedback based on that and the questions tend to continue:

Some of the feedback I have received asked about the Encryption of the UsernameToken in the ResponseStream in the example given above. Here is a sample question:

Encrypting the username token using the public key of the server ensures
that the password is encrypted in the request to the server. What happens
when the response from the server is sent to the client ? I have looked at the
the trace the output tace at the client has no password in clear text. But
the input trace on the client has a clear text password. Why ?

The username credentials returned will follow that of the request method. So, if you send a SendPlainText mode of the PasswordOption in a request [even though you encrypt the UsernameToken afterwards], the UsernameToken in the response will be sent back in PlainText as well. This happens, of course, if you added the mutable UsernameToken back into the response stream
 
'Add Mutable Token into the Token Collection of the Response
ResponseSoapContext.Current.Security.Tokens.Add(RetrievedUsernameTokenFromRequestStream)

We cannot re-do the process we did earlier in the RequestStream by encrypting the UsernameToken again. If you remember, that was done because we had to do some Hash-Digest comparision with the Hash value stored in the user db against the Hash value generated from the Password sent in the RequestStream. Thus, the Password send have to be in PlainText mode. However, we will encrypt the UsernameToken so that it doesnt get seen on the wire. We encrypt it with the Recipient's PublicKey for the Recipient's perusal. At least, an encrypted token CAN be decrypted, a Hashed one CANNOT.
 
However, we cannot do the same in the reverse ResponseStream. This is because we cannot encrypt the Recipient's SecurityToken with the Recipient's key. The Recipient machine would not know how to decrypt it.

ResponseSoapContext.Security.Elements.Add(New EncryptedData(eTok, "#" & eTok.Id))

doesnt make any sense and would be invalid and the Recipient would respond with a SOAP Client error:
 
    ApplicationException: WSE507: The order of security elements and security tokens
    will cause a processing failure on the receiving end, and they must be reordered
    to create a valid message.
 
To hack around this constraint in WSE 2.0, the best alternative I could think of and tried is to intercept the process and force the UsernameToken to be sent back with a SendHashed or better, with a SendNone Option. This can be done by typeCasting the SecurityToken that is retrieved from the earlier RequestStream to that of a UsernameToken. Then retrieve all the necessary credentials of the casted UsernameToken (eg. Username, Password) and send that details into a new instantiated UsernameToken. Then, add this newly created mutable UsernameToken into the ResponseSoapContext Stream.

'Retrieve the Signing Token from the Request Message

Dim eTok As SecurityToken = GetBodySigningToken(RequestStream)

'Retrieve the Encrypting X509Security Token from the Request Message

Dim sTok As X509SecurityToken = GetBodyEncryptingToken(RequestStream)

'CAST the SecurityToken into a UsernameToken type

eTok = CType(eTok, UsernameToken)

'Force the process to send back a Hashed or NO Password

Dim ut As UsernameToken = New UsernameToken _CType(eTok, UsernameToken).Username, CType(eTok, UsernameToken).Password, PasswordOption.SendHashed)

'Retrieve the same Cert from the Local Machine store and Check if it supports Digital Signing

Dim sX509KeyID As String = Convert.ToBase64String(sTok.Certificate.GetKeyIdentifier)
sTok = Helpers.GetSigningX509Cert(sX509KeyID)

'Add Mutable Token into the Token Collection of the Response

ResponseSoapContext.Security.Tokens.Add(ut)
ResponseSoapContext.Security.Tokens.Add(sTok)

'Add the Message Signature into the message

Resp.Security.Elements.Add(New MessageSignature(sTok))

'Add the Encrypted data into the message

Resp.Security.Elements.Add(New EncryptedData(ut))

From the ResponseStream generated, you will be able to look at the UsernameToken sent back now to the Recipient. However, the Password will be Hashed or there may be NO Password at all (if you configured to be sent back with a PasswordNone Option). Below is the trace snippet sent back from the Server to the Recipient.
 
        <wsse:UsernameToken...>
          <wsse:Username>TestAccount</wsse:Username>
          <wsse:Password Type=...>wc9Xl04zDgbbd0NIrOuHuRcsRVs=</wsse:Password>
          <wsse:Nonce>qr7saTsm5H/YNSjIl3w2kA==</wsse:Nonce>
          <wsu:Created>2004-08-05T09:38:53Z</wsu:Created>
        </wsse:UsernameToken>

Of course, if the Service Consumer has their X.509 Digital Certs as well, we can always embed a binarySecurityToken representation of the client's Public Key into the SOAP Request stream and then, in the Service Response Stream, encrypt the Consumer's UsernameToken with his own Public Key taken from the binarySecurityToken representation and dispatches it. However, this is not an elegant solution as

  1. Most Service Consumers do not have their own X.509 Digital Certs and therefore, we have to cater for those who dont. This means extra processing power and code is needed to parse the SOAP Message to check for the binarySecurityToken and extra logic is required to hash it back using the above method if the binarySecurityToken is not found.
  2. Message Payload will increase with any type of encryption as compared to hash digest and with the attachment of the binarySecurityToken as well.

Do let me know if this works for any of you or, if you have better suggestions.

Thursday, November 04, 2004 6:06:28 AM (Malay Peninsula Standard Time, UTC+08:00)  #    Disclaimer 
  • Blog reactions