How can I change the namespace prefix of the timestamp element in the security element of a soap request (wcf)

207 Views Asked by At

For clearity, I am using wcf in .NET 4.8.1, because .NET Core doesn't support message security.

I am consuming a soap webservice that requires both transport security and message security, all based on certificates (one private key certificate for the transport security, another private key certificate for the signature and one public key certificate for the message encryption). I needed to write a custom ClientCredentials class to support a second client certificate, because by default you can only specify one. That part is working fine.

When I send a request, the receiver is getting the error 'No signed timestamp present in request', but there really is a signed timestamp present in the request. I validated the signature with SignedXml and that indicates that the signature is valid.

I am not sure for 100%, but my assumption is that the timestamp is not being recognized by the receiver because of the namespace prefix that's being used.

The timestamp that's being created in my soap message by WCF is als follows:

<s:Envelope xmlns:s=http://www.w3.org/2003/05/soap-envelope xmlns:u=http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd>

   <s:Header>

      <o:Security s:mustUnderstand="1" xmlns:o=http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd>

                    <u:Timestamp u:Id="uuid-f0fe5620-a332-42ea-8520-f045137ee92e-1">

                              <u:Created>2022-12-15T14:24:29.157Z</u:Created>

                              <u:Expires>2022-12-15T14:29:29.157Z</u:Expires>

                    </u:Timestamp>

The receiver did have success with a message that's being created by himself, in which the timestamp is as follows:

<wsu:Timestamp wsu:Id="id-2-31b572d3a7dc8a1162f180b927789ef7">

        <wsu:Created>2022-12-19T13:32:19.110501977Z</wsu:Created>

        <wsu:Expires>2022-12-19T13:37:19.110Z</wsu:Expires>

</wsu:Timestamp>

The main difference that I see is that in my message the namespace prefix u: is being used, while in the self made message of the receiver, the namespace prefix wsu: is being used.

I am using a custom binding with a SecurityBindingElement on which the IncludeTimestamp property is being set to true. This is a part of the code:

var securityElement = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10, true);

securityElement.IncludeTimestamp = true;

securityElement.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;

securityElement.EnableUnsecuredResponse = true;

I can't find a way to change the namespace prefix of the timestamp element. With a MessageFormatter you can change a namespace prefix of the body and subelements of the body, but you don't seem to have access to the ws-security headers. It's also important to change it at the right stage in the pipeline, because it must be changed before the signature is being created. Otherwise the signature will not be valid anymore.

I know that semantically there is no difference between a u: namespace prefix and a wsu: namespace prefix, but I can't find another reason why my message is being rejected.

Any help would be appreciated.

When I send a message without a timestamp, but with a signature for just the body, the message is being accepted (when the require timestamp policies are being disabled by the receiver). So the technique of creating the signature seems to work. Also the transport security and the decryption of the message by the receiver is working fine.

I tried to write a custom MessageFormatter, but I don't seem to have access to the security headers at that stage. I succeeded to get the namespace prefix wsu: in the envelope, but then it's not being used in the timestamp element. In the timestamp element the namespace is being redefined with the u: namespace prefix.

I also tried to write a ClientMessageInspector, but also at that stage I don't seem to have access to the security headers in the request.

0

There are 0 best solutions below