Kristian Kristensen’s Blog


Getting WCF to talk to a Java AXIS 1.X and WSS4J Web Service – Part 2 of 3

Posted in Code,WCF by Kristian Kristensen on the December 12th, 2010

This is the second post in a series on my woes in integrating to a Java AXIS 1.X and WSS4J web service. Read Part 1, Part 2, Part 3.

The first service interaction requires signing the message, timestamping it and include the certificate that the request should be signed with in a BinarySecurityToken. The key discovery was in this forum thread that lead me to using the mutualCertificate option for the authentication method as well as where to tweak the timestamp inclusion. With this in place I could call my service and get to the next step. This was a policy error on the WCF side meaning my client that the order of the returned security elements didn’t line up. This was a major breakthrough because it meant that I was now calling the service from WCF. Via Fiddler I could also see what was going over the wire and that the returned data was in fact valid! Solving the exception I received on my WCF side proved to be fairly easy. WCF is strict in enforcing the order that the WS-Security elements appear in the response, but OOB an attribute (“securityHeaderLayout”) is provided that relaxes this requirement (Incorrect order of security elements “lax”).
The full binding configuration is seen below.

<customBinding>
        <binding name="SkatSignatureTimestamp">
          <textMessageEncoding messageVersion="Soap11" />
          <security allowSerializedSigningTokenOnReply="true" authenticationMode="MutualCertificate"
            requireDerivedKeys="false" securityHeaderLayout="Lax" includeTimestamp="true"
            keyEntropyMode="ClientEntropy" messageProtectionOrder="SignBeforeEncrypt" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
            requireSecurityContextCancellation="false">
            <secureConversationBootstrap />
          </security>
          <httpsTransport />
        </binding>
        </customBinding>

To configure the certificates used to sign an endpoint behavior needs to be applied. I’ve been given a test certificate that I can use by the service vendor and I imported it to my computers certificate store. Then configuring the certificates used was fairly easy. The behavior is seen below.

          <behaviors>
      <endpointBehaviors>
        <behavior name="SkatCertificates">
          <clientCredentials>
            <clientCertificate findValue="xx xx xx xx" x509FindType="FindByThumbprint" />
            <serviceCertificate>
              <!--
     Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
     is in the user's Trusted People store, then it will be trusted without performing a
     validation of the certificate's issuer chain. This setting is used here for convenience so that the
     sample can be run without having to have certificates issued by a certificate authority (CA).
     This setting is less secure than the default, ChainTrust. The security implications of this
     setting should be carefully considered before using PeerOrChainTrust in production code.
     -->
              <defaultCertificate findValue="xx xx xx" x509FindType="FindByThumbprint" />
              <authentication certificateValidationMode="PeerOrChainTrust" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    

Setting up the client section is a matter of coupling the binding configuration with the behavior configuration. The thing to remember is the “identity” element that needs to match up with the identity in the certificate used, ie. the certificate alias. You can find this name by opening the certificate in Certificate Manager in Windows and look for the value of “Issued To”.

<client>
      <endpoint address="https://the-external-service-url.dk"
        behaviorConfiguration="SkatCertificates" binding="customBinding"
        bindingConfiguration="SkatSignatureTimestamp" contract="IContract"
        name="Service">
        <identity>
          <dns value="certificate identity" />
        </identity>
      </endpoint>
      </client>

Calling the service now will result in an error. The problem was that the SOAP body is being encrypted and the service expects the message to only be signed. Fixing this is done by adding an attribute to the ServicePortType interface automatically generated by the “Add Service Reference” in Visual Studio. The attribute that needs to be set is the ProtectionLevel attribute:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://rep.oio.dk/skat.dk/eindkomst/",
  ConfigurationName = "Service_IServicePortType",
  ProtectionLevel = ProtectionLevel.Sign
]
public interface IndkomstOplysningKlassiskAbonnentHent_IServicePortType {
   //interface implementation
}

This instructs WCF to only Sign the message. Other values of ProtectionLevel are None, and EncryptAndSign. Issuing the service call now results in a correct message to be sent over the wire.

The next part deals with the second type of service call I had to make, which had its own set of security requirements.

  • If you like my writing you should subscribe to my RSS feed.

    One Response to 'Getting WCF to talk to a Java AXIS 1.X and WSS4J Web Service – Part 2 of 3'

    Subscribe to comments with RSS or TrackBack to 'Getting WCF to talk to a Java AXIS 1.X and WSS4J Web Service – Part 2 of 3'.


    1. on December 13th, 2010 at 3:54 pm

      [...] post in a series on my woes in integrating to a Java AXIS 1.X and WSS4J web service. Read Part 1, Part 2, Part [...]

    Leave a Reply

    You must be logged in to post a comment.