WCF rejects messages with additional signed elements

1.7k views Asked by At

We have a WCF 4.0 service over https that allows the client to sign the message to identify themselves. We can then use the cert to give the client the proper rights on the back end. This works fine when a WCF 4.0 client sends the request, but when a non-WCF attempts to send the request, it fails with the following: CryptographicException: Unable to resolve the '#Id-{Guid goes here}' URI in the signature to compute the digest. Upon inspecting the clients request, this failure occurs whenever anything more than the To and Timestamp nodes are signed. The non-WCF client expects to sign the body, Action, MessageID, and ReplyTo sections. Can WCF be configured to expect and allow these signatures or, better yet, allow them if they are there but don't fault if they aren't?

Service config file:

<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<extensions>
  <behaviorExtensions>
    <add name="wsdlExtensions" type="MyWCFElements" />
  </behaviorExtensions>
  <bindingElementExtensions>
    <add name="httpsViaProxyTransport" type="MyWCFElements" />
  </bindingElementExtensions>
</extensions>
<behaviors>
  <endpointBehaviors>
    <behavior name="WsdlBehavior">
      <wsdlExtensions singleFile="true" />
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="WebServicesServiceBehavior">
      <serviceMetadata httpsGetEnabled="false" httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
      <serviceAuthenticationManager serviceAuthenticationManagerType="MyServiceAuthenticationManager" />
      <serviceAuthorization serviceAuthorizationManagerType="MyServiceAuthorizationManager" />
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyUserNameValidator" />
        <clientCertificate>
          <authentication certificateValidationMode="PeerTrust" trustedStoreLocation="LocalMachine" />
        </clientCertificate>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>
<bindings>
  <customBinding>
    <binding name="SignedWebServicesF5BindingConfig">
      <textMessageEncoding />
      <security authenticationMode="CertificateOverTransport" allowInsecureTransport="true" requireDerivedKeys="false" securityHeaderLayout="Lax" />
      <httpsViaProxyTransport />
    </binding>
  </customBinding>
</bindings>
<services>
  <service behaviorConfiguration="WebServicesServiceBehavior" name="WebService">
      <endpoint address="signed" binding="customBinding" behaviorConfiguration="WsdlBehavior" bindingConfiguration="SignedWebServicesF5BindingConfig" contract="IWebServicesContract" name="SignedWebServices"/>
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>

1

There are 1 answers

0
Shawn Hubbard On BEST ANSWER

After working with Microsoft, the answer seems to be that you cannot use CertificateOverTransport and sign the message body, which is what our client was attempting to do. We moved to MutualCertificateDuplex and changed the ProtectionLevel of our response to ProtectionLevel.None (since we aren't interested in signing the response). We're now able to receive a request and get a response over https, so we can still rely on the transport for encryption while the security of the message is maintained at the message level, not the transport level.

Hope this helps someone else, this seems to be fairly common in WCF interop scenarios but there isn't a ton of guidance about this on the web.