Wednesday, October 29, 2008

Interoperability Gotcha: SslContextToken Negotiation & WS-Policy

@YaronNaveh

When you try to import a WCF-created WSDL from a Java client such as Metro (WSIT) you may get the following error:



com.sun.xml.ws.security.impl.policy.Constants log_invalid_assertion
WARNING: SP0100: Policy assertion Assertion[com.sun.xml.ws.policy.sourcemodel.DefaultPolicyAssertionCreator$DefaultPolicyAssertion] {
  assertion data {
   namespace =   'http://schemas.microsoft.com/ws/2005/07/securitypolicy'
   prefix = 'mssp'
   local name = 'SslContextToken'
   value = 'null'
   optional = 'false'
   ignorable = 'false'
   attributes {
   name = 'http://schemas.xmlsoap.org/ws/2005/07/securitypolicy:IncludeToken', value = 'http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient'
}
}
  no parameters
  nested policy {
   namespace version = 'v1_5'
   id = 'null'
   name = 'null'
   vocabulary {
   1. entry =   'http://schemas.microsoft.com/ws/2005/07/securitypolicy:MustNotSendCancel'
   2. entry =   'http://schemas.xmlsoap.org/ws/2005/07/securitypolicy:RequireDerivedKeys'
   }
   assertion set {
Assertion[com.sun.xml.ws.policy.sourcemodel.DefaultPolicyAssertionCreator$DefaultPolicyAssertion] {
  assertion data {
   namespace = 'http://schemas.microsoft.com/ws/2005/07/securitypolicy'
   prefix = 'mssp'
   local name = 'MustNotSendCancel'
   value = 'null'
   optional = 'false'
   ignorable = 'false'
   no attributes
  }
   no parameters
   no nested policy
   }
Assertion[com.sun.xml.ws.policy.sourcemodel.DefaultPolicyAssertionCreator$DefaultPolicyAssertion] {
   assertion data {
   namespace =   'http://schemas.xmlsoap.org/ws/2005/07/securitypolicy'
   prefix = 'sp'
   local name = 'RequireDerivedKeys'
   value = 'null'
   optional = 'false'
   ignorable = 'false'
   no attributes
   }
   no parameters
   no nested policy
   }
  }
}
} is not supported under Token assertion



The reason is that the WCF WS-Policy contains this section:



<mssp:SslContextToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" xmlns:mssp="http://schemas.microsoft.com/ws/2005/07/securitypolicy">
<wsp:Policy>
...
</wsp:Policy>
</mssp:SslContextToken>


This means that your WCF service uses X.509 certificates negotiation. In such a scenario, clients use the server X.509 certificate for encryption. The unique here is that clients are not required to have this certificate out of band (as in most cases), rather they get this certificate using a SOAP-level negotiation. This is implemented as an extension over WS-Trust. While this is not strictly a proprietary Microsoft solution, Microsoft was the only one to implement it so far. In short - X.509 negotiation (SslContextToken) is not interoperable. Unfortunately(?) the default configuration of a WCF service is to use this negotiation. To turn it off either update your WsHttpBinding configuration:



   <message clientCredentialType="None" negotiateServiceCredential="false" />
</security>


Or choose the correct scenario in your CustomBinding:


<security authenticationMode="AnonymousForCertificate">
   <secureConversationBootstrap />
</security>

You can also use the equivalent cases for username authentication. Note that any clients (including WCF ones) will now need to have the service certificates defined out of band.

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

Monday, October 27, 2008

Best Forums For Web Services Interoperability

@YaronNaveh

If you are writing a JAX-WS web service then you must be familiar with the Java.Net support forums. If you are a WCF developer you have surely bookmarked the MSDN forums. But what if you are an Axis2 developer seeking for interoperability with WCF? Or a .Net 2.0 tester having trouble with an XFire service? This post will give you a hint on where to ask your questions.

Axis2 / Rampart
If you need to work with an Axis2 service you can try to check if there is a bug already open on your case in the issues tracker:

http://issues.apache.org/jira/browse/AXIS2

You can drop a question at the WSO2 forums - This project is a server based upon Axis2 and developed by the same people who develope Axis2:

http://wso2.org/forum

Another good forum is the JavaRanch:

http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=forum&f=51

If you have a security question you better check in the Rampart (Axis2 security module) issues tracker:

http://issues.apache.org/jira/secure/BrowseProject.jspa?id=12310610

(You can also open a new issue as a "question")

Or again in WSO2

http://wso2.org/forum


Metro - JAX-WS - Tango - WSIT

JAX-WS is a standard Java interface for web services. Metro is a reference implementation of it written by Sun. Tango (=WSIT) adds WS-* support to Metro.

For this project the support is concentrated in the Metro forum:

http://forums.java.net/jive/forum.jspa?forumID=46

Or the binary web services forum:

http://forums.java.net/jive/forum.jspa?forumID=44


.Net 2.0 / WSE2 / WSE3
.Net 2.0 is the previous generation of Microsoft's web services stack. WSE2 and WSE3 are the WS-* implementation for .Net 2.0. The best places to ask on related issues are the Asp.Net XML web services forum:

http://forums.asp.net/28.aspx

And the MSDN forum:

http://social.msdn.microsoft.com/forums/en-US/asmxandxml/threads/


Windows Communication Foundation (WCF)
WCF is the latest generation of Microsoft's SOAP & WS-* stack. All related issues should go to the MSDN forum:

http://social.msdn.microsoft.com/forums/en-US/wcf/threads/


XFire / CXF
XFire is a Java Soap stack. Some time ago it has joined forces with Celtix to create a new Soap stack named CXF (CeltiXFire).

Questions should go to the mailing list:

http://www.nabble.com/cxf-user-f16914.html

If you still have question on old XFire go to nabble:

http://www.nabble.com/XFire-f8896.html


Spring-WS
Spring-WS is another Java soap stack. Here is its forum:

http://forum.springframework.org/forumdisplay.php?f=39

JBossWS
JBoss is a well known Java application server and it also has a web services framework:

http://www.jboss.com/index.html?module=bb&op=viewforum&f=200

gSOAP (C++)
gSoap is a familiar c++ soap stack. The discussion forum requires registration:

http://tech.groups.yahoo.com/group/gsoap/

But meanwhile you can open a support request or look at the open bugs:

http://sourceforge.net/tracker2/?group_id=52781

WSO2 WSF/ C / C++ / PHP / Ruby /...
WSO2 mentioned above also develop Axis2 compatible toolkits for various platforms. If you have a question on any of them you can ask here:

http://wso2.org/forum

If you have any additions to the list above please add a comment and I'll update it. Of course you're alwayes welcomed to share with us in this blog any interesting interoperability issue you have.

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

Friday, October 24, 2008

X.509 interoperability & SubjectKeyIdentifier

@YaronNaveh

I've already highlighted some X.509 interoperability issues before. This time we will talk about correctly referencing certificates.

A client that uses a server certificate in order to encrypt a message needs to reference this certificate in code. Inside the message the reference would typically look like this:


  <o:SecurityTokenReference>
   <keyName>CN=someServer</keyName>
  </o:SecurityTokenReference>


Or this:

  <o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">sWTM4Q7da6N9q2kYYYhn+jnnsv4=</o:KeyIdentifier>


Or this:


  <wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"<bBwPfItvKp3b6TNDq+14qs58VJQ=</wsse:KeyIdentifier>


Or in any of a few other formats.

The required format can be declared in WS-Policy. For example:


<wsp:Policy>
   <sp:RequireKeyIdentifierReference />
   <sp:WssX509V3Token10 />
</wsp:Policy>


However many services do not have WS-Policy so it's not a must.

There are various ways to get this SKI from a certificate. Some of them are:

  • The certificate might contain an out-of-band generated SKI inside it as an "extension".



  • An SHA1 thumbprint is calculated out of the certificate raw data.

  • The certificate serial number and issuer name are used

  • The certificate subject name is used

  • The SKI needs to be calculated from the certificate using some algorithm

    Guess which option causes us most trouble? Right, the last one. The problem is that it is not concrete enough. There were a few ways to generate this SKI and so there were misunderstandings between Java and Microsoft applications and even between different versions of the same frameworks.

    Let's take a sample certificate as an example. First convince yourself that it does not contain SKI extension:



    Now look at the format WebSphere 6 server would expect:


    M9WWSXczVFt2otJ3adPjfmbUxU8=


    WSE2 would generate:


    bBwPfItvKp3b6TNDq+14qs58VJQ=


    And WSE 3 generates this one:


    SdPjfmbUxU8=


    With WCF you would get the following exception:


    System.NotSupportedException:

    "'X509SecurityToken' does not support 'X509SubjectKeyIdentifierClause' creation."


    As WCF does not work with certificates that do not have SKI when the latter is explicitly required - and that's what I did for this sample.

    So by all and all we've got 4 different SKI's out of one certificate!

    Out of these 4 frameworks there is a way to interoperate using SKI and X.509 that does not contain SKI extension between the following:



    Note: It is possible to interoperate between these platform in various other ways. If you now design your system you should use these ways. The information here is provided for those who are already working with a given systems.

    So how can we reach this interoperability?

    To interoperate with WebSphere all you need to do is to change WSE2 configuration to:


       <microsoft.web.services2>
         <security>
           <x509 ... useRFC3280="true" />
    ...
         </security>
       </microsoft.web.services2>


    And it will generate a WebSphere-like SKI (which is more standard all around).
    To interoperate between WSE2 and WSE3 you need to leave the default WSE2 configuration as is and change WSE3:


    <microsoft.web.services3>
       <security>
         <keyIdentifierMapping>
           <x509 ... skiMode="CAPI" />
    ...
         </security>
       </microsoft.web.services3>


    Note: even though WSE 3 allows skiMode="RFC3280" as WSE2 does the calculation is different and will not interoperate.

    As for the rest - you would have to use a certificate with an SKI extension or use another type of reference instead.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!
  • What Happened To The WCF Forum In MSDN?

    @YaronNaveh

    Update: Forum is up and running again.

    It's been over a day now that the WCF forum in MSDN is down. However for anyone in a need to raise an urgent development issue it looks like forever. It was just upgraded to its new version two week ago and now this. It's also strange that all other MSDN forums that were upgraded to the new version are up. I'm not suggesting there's a conspiracy of any sort but it's still strange. Why couldn't it be the WPF Forum or even Windows Live Controls Development Forum?

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Tuesday, October 21, 2008

    Don't blindly trust WCF logging

    @YaronNaveh

    WCF logging is a very important debug feature in .Net 3.5. However you shouldn't always trust what you see...

    Removing nonce and passwords
    The first case where the logging may mislead is when security mechanisms such as username, password or nonce are used. For security reasons the log will no show them (see image bellow)




    No WS-Addressing
    The WS-Addressing standard is used in some of the bindings. When it is not used (as in basicHttpBinding or certain customBinding) the log will still show you something like:


    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/EchoArr</Action>





    However this will not go on the wire as can be proved with fiddler:




    This can actually also be proved by turning the WCF logging at the transport level:




    So we can't really say that WCF showed something wrong here - after all the service level logging does not go on to the wire - but it is confusing.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Thursday, October 16, 2008

    WCF & WSE Interoperability

    @YaronNaveh

    WSE is the previous generation of Microsoft WS-* stack. For this reasons a lot of Microsoft shops are in a need to interop between WSE & WCF. I'm not going to invent the wheel here - there's a great article in MSDN on this.

    There is one delicate point I'd like to emphasize. WCF supports WS-Policy which is a way for a service to specify what WS-* requirements it has (e.g. security, attachments). The policy is contained inside the wsdl:



    <wsdl:definitions name="Service" targetNamespace="http://tempuri.org/">
     <wsp:Policy wsu:Id="WSHttpBinding_IService_policy">
       <wsp:ExactlyOne>
        <wsp:All>
         <sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
          <wsp:Policy>
           <sp:ProtectionToken>
    ...


    When a WCF client is generated using "Add service reference" the app.config is automatically synchronized with the WS-Policy from the service wsdl.

    WSE does not support this usage of WS-Policy in any of its versions. So when a wsdl that was created using WSE is imported using WCF the app.config needs to be updated manually (or via the config editor). One exception is SSL which WCF can identify from the service url.

    For a WSE WSDL, WCF generats a basicHttpBinding by default. In most cases a customBinding would be required in order to reach interoperability on the wire using rich security options, soap12 and MTOM.

    I recently saw an error that a WSE server returned for a WCF client:


    Header http://schemas.xmlsoap.org/ws/2004/08/addressing:Action for ultimate recipient is required but not present in the message.


    A short investigation showed that the WCF client used the auto-generated app.config with its basicHttpBinding. That's why it did't send any WS-Addressing headers as the error indicates. The solution is of course to manually edit app.config and move to an appropriate customBinding.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!

    Wednesday, October 15, 2008

    Interoperability Gotcha: doc/lit/wrapped

    @YaronNaveh

    Every wsdl has a "style" and an "encoding". They only set the soap message format on-the-wire so they do not matter for the most developers most of the time. However it is highly recommended to always use style=document and encoding=literal to increase interoperability. For example:


    <wsdl:operation name="MyOperation">
      <soap12:operation soapAction="http://tempuri.org/MyOperation" style="document" />
      
        <soap12:body use="literal"/>
    ...


    There is a special recommended style to write doc/lit wsdls: doc/lit/wrapped. In this format each message is named with the operation name suffixed by "request" or "response". The message contains only one part named "parameters" (this name never appears in the soap in doc/lit so it shouldn't matter). There are other requirements - see more details at Anne's blog. For example (pseudo wsdl):



    <xs:schema>
      <xs:element name="MyOperationRequest">
         <xs:complexType>
           <xs:sequence>
    ...
           </xs:sequence>
         </xs:complexType>
       </xs:element>
    </xs:schema>

    ...
    <wsdl:message name="MyOperationSoapIn">
       <wsdl:part name="parameters" element="tns:MyOperationRequest">
       </wsdl:part>
    </wsdl:message>
    ...
    <wsdl:portType name="MyOperationSoap">
       <wsdl:operation name="MyOperation">
        <wsdl:input message="tns:MyOperationSoapIn"/>
    ...
      </wsdl:Operation>
    <wsdl:PortType />



    There are a few advantages to doc/lit/wrapped among them a cleaner model and a more expressive soap message. However this style raises a few interoperability issues:


    Axis2 code generation
    If you've read Anne's explanation you know that the root element in the message is redundant (since it always has to be used anyway) and so the generated stub looks more complex than it should. Keith explains how to solve this.


    WCF DataContractSerializer
    WCF has a few flavours of serializers. DataContractSerializer is the recommended one. However this serializer can only be used in doc/lit/wrapped. So If your use svcutil to generate a proxy like this:


    SvcUtil.exe /t:code /serializer:DataContractSerializer /s /out:IService.cs /n:*,myNamespace /ixt myService.wsdl


    You might get the following error:


    Warning: The optional WSDL extension element 'body' from namespace 'http://schem
    as.xmlsoap.org/wsdl/soap/' was not handled.
    XPath: //wsdl:definitions[@targetNamespace='http://myNamespace']/wsdl:bind
    ing[@name='MyBinding']/wsdl:operation[@name='MyOperation']/w
    sdl:output[@name='MyOperationResponse']


    You will get this error if your wsdl does not comply to doc/lit/wrapped in one or more ways. For example if your part names are not "parameters". The way to solve this is either to change the part names to "parameters" (and fix all other issues) or to not force svcutil to use DataContractSerializer:


    SvcUtil.exe /t:code /s /out:IService.cs /n:*,myNamespace /ixt myService.wsdl


    In this case WCF will downgrade itself to use the .Net 2.0 XmlSerializer. This serializer is not bad at all and was used in .Net 2.0 applications. It does have a less optimal performance than the new serializer but you can use it in production applications if you need. Dan wrote an interesting comparison of the two serializers.

    .Net 2.0 derived types
    I won't dive into details with this one. Generally speaking .Net 2.0 might try to serialize as doc/lit/wrapped some wsdls which are not really in this format and so it can fail code generation. One example is when the wrapper element has derived types.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!