Saturday, November 22, 2008

Securing Web Services With Username/Password

@YaronNaveh

Many web services authenticate clients using username/password. In the soap message it looks like this:


<wsse:Username>yaron</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">1234</wsse:Password>


You can notice that the username/password are clear (not encrypted). This means that everyone that can see this message can steal the password.

There are typically 3 ways to overcome this.

1. Sending the hashed password only:


<wsse:Username>yaron</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">iuacnq2G/t0nWcYgCMx66UtFlxA=</wsse:Password>


Where the digest is calculated from the password, a timestamp and a nonce.
However this is not really secure. A hacker can use a dictionary attack to extract the password.

2. Protecting the username with SSL.
This is a valid option but is limited to HTTP web service only and denies us from some of the rich WS-Security options. There are some other transports which are inherently secured (like SSL passthrough of load balancers as F5's BIG-IP) but I will not discuss them here.

3. Protecting the username with message-level X.509 certificate.
This is another valid option but sometimes more complex to implement.

In practice if you want to use username/password you would need to decide between options 2&3. Some frameworks, like Microsoft's WCF, even prevents you from using option #1 at all. Nevertheless there are a few exceptions where option #1 is valid:

  • Your network is inherently secured so you are not afraid of password stealers.

  • You are required to interoperate with a service that requires to send clear username/password


  • If you are using WCF and have the above needs you should use the WCF ClearUsernameBinding.

    @YaronNaveh

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

    Thursday, November 13, 2008

    Cryptic WCF error messages (part 3 of N)

    @YaronNaveh

    When you use X.509 certificates you might get the following exception on the client:


    Identity check failed for outgoing message. The expected DNS identity of the remote endpoint was 'localhost' but the remote endpoint provided DNS claim 'WSE2QuickStartServer'. If this is a legitimate remote endpoint, you can fix the problem by explicitly specifying DNS identity 'WSE2QuickStartServer' as the Identity property of EndpointAddress when creating channel proxy.




    The error happens while client tries to authenticate the server. It does so by comparing the server identity as appears in its X.509 to the server identity you configured to expect. If you haven't configured it than it assumes the service url domain name is the expected identity (for example "localhost" is expected for "http://localhost/MyService.svc").

    The solution is to do exactly as the error tells us: Define the expected identity in the configuration. In app.config it can look something like this:


    <client>
    <endpoint address="http://localhost:13037/WCFService54/Service.svc"
    contract="ServiceReference1.IService"
    name="WSHttpBinding_IService">
    <identity>
    <dns value="localhost" />
    </identity>

    </endpoint>
    </client>


    and in the configuration editor as bellow:

    @YaronNaveh

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

    Inconsistent "soap:mustUnderstand" in .Net 2.0

    @YaronNaveh

    It seems that .Net 2.0 web services do not handle soap:mustUnderstand attribute in a consistent manner. This attribute can appear over soap headers in order to require the processing party to fail itself if it cannot process this specific header. Example:


    <soap:Envelope>
     <soap:Header>
      <SomeHeader soap:mustUnderstand="1">1234</SomeHeader>
     </soap:Header>
     <soap:Body>
      ...
     </soap:Body>
    </soap:Envelope>


    Now if our server does not understand SomeHeader an exception should be thrown.

    To begin with, when a SoapHeader is defined in the service/proxy, .Net will not allow us to mark it as "required" since it is considered obsolete:



    This is not really related to mustUnderstand: When the proxy contains required=true it means (or should have at least) that the proxy will fail itself if this value is not supplied by the user. This is different than omitting a mustUnderstand header which will cause the server to fail.

    But the real inconsistency comes with mustUnderstand: When a .Net 2.0 web service gets soap:mustUnderstand header it will always ignore it even if it was not understood. On the other hand, when a .Net 2.0 web service client gets such an header in a response from the server it will throw the following exception:


    SOAP header SomeHeader was not understood.

    Be aware of this inconsistency when you build or consume .Net 2.0 web services.

    @YaronNaveh

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

    Monday, November 10, 2008

    Web Services XML: Nullable AND Optional xsd:string

    @YaronNaveh

    In xml an element can be both optional and nillable:


    <s:element name="Name" type="s:string" minOccurs="0" nillable="true" />


    So in xml this element can have a value:


    <wrapper>
       <s>123</s>
    </wrapper>


    Be NULL:


    <wrapper>
       <s xsi:nil="true" />
    </wrapper>


    Or be omitted at all:


    <wrapper />


    This is a challenge to many web services frameworks since when generating proxy code an element is usually mapped to one language variable. A variable in a programming language does not natively support metadata such as being "nullable" or "optional".

    In some frameworks the solution is to add a "controller" field. For example some Java frameworks would create something like this:


    setName(String Name) {}
    setNameNillable(bool isNillable) {}
    setNameOptional(bool isOptional) {}


    In .Net 2.0 part of this informaiton is in a controller field and part in .Net attributes. For example a nillable string is:


    [System.Xml.Serialization.XmlElement(IsNullable=true)]
    public string s;


    And an optional int is:


    public int i;
    [System.Xml.Serialization.XmlIgnore()]
    public bool iSpecified;


    What happens in .Net when an element is both nullable and optional?
    There is no problem with an int - we can use System.Nullable:


    public int? i;
    [System.Xml.Serialization.XmlIgnore()]
    public bool iSpecified;


    So now "i" can both have a value of null and seperately be specified as ommited.

    String is more challenging since it can have null from the first place so "string?" is meaningless. We would expect to have:


    [System.Xml.Serialization.XmlElement(IsNullable=true)]
    public string s;
    [System.Xml.Serialization.XmlIgnore()]
    public bool sSpecified;


    However for some reason .Net does not generate this for the client side so it does not support out of the box a string which if both optional and nullable.
    The solution is to manually add the sSpecified element and the XmlIgnore attribute as above to the client proxy or the server side code.
    Note: For the client proxy updating the service reference will override any such change so use this method only if you have no other choice. For example use it when you try to interoperate with a framework that requires this.

    @YaronNaveh

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

    .Net 2.0 Web Services: Raw Text Response

    @YaronNaveh

    Let's say you want your .Net 2.0 web service to return a simple string without any wrapping element (except the necessary minimum). Like this for example:


    <soap:Body>
      <HelloWorldResponse xmlns="http://tempuri.org/">
       Hello World
      </HelloWorldResponse>
    </soap:Body>


    If you will use the default service template:


    [WebMethod]
    public string HelloWorld() {
    return "Hello World";
    }


    You'll get a string wrapped with an element "HelloWorldResult":


    <soap:Body>
      <HelloWorldResponse xmlns="http://tempuri.org/">
       <HelloWorldResult>
        Hello World
       </HelloWorldResult>
      </HelloWorldResponse>
    </soap:Body>



    So how to return a raw unwrapped text?
    Just add the "return" attribute in this way:



    [WebMethod]
    [return: System.Xml.Serialization.XmlText()]
    public string HelloWorld() {
    return "Hello World";
    }

    @YaronNaveh

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

    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!

    Cryptic WCF error messages (part 5 of N)

    @YaronNaveh

    This one isn't that cryptic actually but its cause is not always clear:


    System.TimeoutException:

    The request channel timed out while waiting for a reply after 00:01:00. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout.


    There can be various reasons why a proxy would throw such an exception with the main one being that the server is not available. However one other reason is that the maximum number of allowed sessions was reached. Some bindings (e.g. wsHttpBinding) under some configurations (e.g. Security or ReliableMessaging) cause the server to open a session with each unique client that accesses the service. A session is closed after the client explicitly closes the proxy or when the client is inactive for some time. There can only be a limited number of open sessions. When this limit is reached clients get the above timeout exception. In case you want to raise this limit you need to increase the number of allowd sessions


    <behaviors>
       <serviceBehaviors>
         <behavior name="ServiceBehavior">
           <serviceMetadata httpGetEnabled="true" />
           <serviceDebug includeExceptionDetailInFaults="false" />
           <serviceThrottling maxConcurrentSessions="90" />
         </behavior>
       </serviceBehaviors>
    </behaviors>


    Or from the configuration editor open the behaviour (#1 in image bellow), add an element (#2) and choose the "serviceThrottling" element (#3). Then change the number of sessions (second image bellow).







    You shouldn't allow too much concurrent sessions as it can hurt service performance. The most important to remember is to explicitly close your proxy after you have finished using it:


    client.Close();

    @YaronNaveh

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

    Interoperability Gotcha: elementFormDefault

    @YaronNaveh

    Recently I was getting an error from a web service indicating that my request is invalid.
    I looked at my request:



    <soap:Body>
      <GetPerson xmlns="http://someOrganization">
         <name>Rick</name>
       </GetPerson>
    </soap:Body>



    And at the schema:



    <s:complexType name="GetPerson">
      <s:sequence>
        <s:element minOccurs="0" maxOccurs="1" name="name" type="s:string" />
      </s:sequence>
    </s:complexType>



    And it seemed valid to me.

    So I asked the service provider to show me an example of a working soap request. And so he did:



    <soap:Body>
       <ns:GetPerson xmlns:ns="http://someOrganization">
         <name>Rick</name>
       </ns:GetPerson>
    </soap:Body>




    You can see that the difference is in the namespace of the inner "name" element: It is from the "http://someOrganization" namespace in my request but from the empty namespace in the working request. For those of you less familiar with xml namespaces: In the previous request "xmlns" defined a default namespace for all elements without prefixes; In this case only elements that explicitly use the "ns" prefix belong to the namespace.

    After a short investigation the cause of this was identified. Let's take a second look at the schema (which is a part of the wsdl file):



    <s:schema elementFormDefault="qualified" targetNamespace="http://someOrganization">



    elementFormDefault can have 2 values:
  • unqualified means that non top level elements should appear as belonging to the empty namespace
  • qualified means that every element should appear as belonging to the targetNamespace of its defining schema

    So my request was valid for the "qualified" option and the provider sample was valid for "unqualified". Since the wsdl contains "qualified" my request is correct after all.

    However - as in many times with interoperability - there is a Gotcha:

    Many web services frameworks poorly implement elementFormDefault

    This effectively means that a server can use "unqualified" format even though the wsdl has "qualified".

    The solutions can be:

    1. Fix the server implementation
    2. Manually change "qualified" to "unqualified" in the wsdl and recreate your client stubs.

    For new services it is recommended to use "qualified" which is also the default for most new soap stacks.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!
  • Tuesday, October 14, 2008

    Cryptic WCF error messages (part 4 of N)

    @YaronNaveh

    Today's exception can happen when X.509 certificates negotiation is used. One case when it is used is when you use wsHttpBinding with:


    negotiateSerciveCredential="True"
    messageClientCredentialType=[anything but "Windows"]


    But there are other cases as well.

    You may get the following exception at the client:


    "SOAP security negotiation with 'http://localhost:13037/WCFService54/Service.svc' for target 'http://localhost:13037/WCFService54/Service.svc' failed. See inner exception for more details."


    The inner exception shows:


    {"The X.509 certificate CN=WSE2QuickStartServer chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.\r\n"}


    The reason for that is that the certificate the server uses is not trusted on the client machine. We can see this by double-clicking on the certificate in the file system or in the windows certificate store:



    You have 2 ways to solve this:

    1. Make sure the service certificate is trusted on the client machine. For example install its issuer certificate in the trusted root store.

    OR:

    2. This is just for testing and should not go to production. You can disable the server authentication by the client: On the client side create a new endpoint behaviour with a "clientCredentials" behaviour element and set its serviceCertificate/authentication/certificateValidationMode to "None".

    The app.config may look like this now:

    <behaviors>
    <endpointBehaviors>
    <behavior name="NewBehavior">
    <clientCredentials>
    <serviceCertificate>
    <authentication certificateValidationMode="None" />
    </serviceCertificate>
    </clientCredentials>
    </behavior>
    </endpointBehaviors>
    </behaviors>


    A picture may be better here:




    Don't forget to link that behaviour to the endpoint:

    <endpoint ... behaviorConfiguration="NewBehavior"... />




    Note that after you solve this error you may see a related cryptic WCF error message.

    @YaronNaveh

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

    Monday, October 13, 2008

    How to validate your WSDL

    @YaronNaveh

    Update: WsiHero is A GUI utility to validate Wsdl / Soap using the latest WSI profile.

    Your service WSDL file is the contract between you and your web service clients. Whether you manually write the WSDL or let your framework automatically generate it for you - you want to make sure it is valid (otherwise you'l have no clients!).

    There is more than one way to define the validity of a WSDL: Does it need to be valid according the WSDL XML schema? Does it need to comply to known best practices? Does it need to be parsed correctly by common soap stacks? There are different ways to test each of these requirements. Commercial tools, like XMLSpy, can help you with some. Today I'll show you a free alternative: the WSI test tool. WSI is the web services interoperability organization and it has defined the WSDL "basic profile" - a set of best practice recommendations for WSDLs. They have also published a tool that can tell you if your WSDL confirms to this profile and today I'll show you how to use it.

    Update: WsiHero is A GUI utility to validate Wsdl / Soap using the latest WSI profile.

    Step 1 - Download the WSI test tool
    Go to the downloads page in the WSI site and download "Interoperability Testing Tools 1.1". It has a C# and a Java version - today we will use the C# one but using the Java is similar.

    Step 2 - Extract the tool
    Just extract the zip to some folder

    Step 3 - Configure the test
    Copy wsi-test-tools\cs\samples\analyzerConfig.xml to wsi-test-tools\cs\bin and open it with a text editor. Change the following values:

  • wsdlURI - Should contain the url for your wsdl, for example http://MyServer/MyService.asmx?WSDL
  • serviceLocation - Should contain the url for your service, for example http://MyServer/MyService.asmx
  • wsdlElement - This is the most confusing one. Your service has at least one endpoint/port. Here you need to define which one you currently want to test. In order to supply this data open your WSDL in internet explorer and notice that its structure is something like:


    <wsdl:definitions ...targetNamespace="http://tempuri.org/" ...
    <!--a lot of tags-->
    <wsdl:binding name="MyServiceSoap"...
    <!--a lot of tags-->


    So take the value of the "targetNamespace" from here and put its value in the "namespace" attribute of the "wsdlElement" element in the configuration. Also take the value of the "name" element and put it in the "wsdlElement" element value. So the "wsdlElement" configuration may look like:


    <wsdlElement type="binding" namespace="http://tempuri.org/">MyServiceSoap</wsdlElement>


    Note: If you have a few "wsdl:Binding" in your wsdl you should repeat this for each one.

    Step 4 - Run the test
    Open command line and go to the wsi-test-tools\cs\bin directory. Then run:


    $> Analyzer


    Step 5 - Analyze the results
    The wsi-test-tools\cs\bin folder now contains a file report.xml. Open it in internet explorer to view the results.





    Update: WsiHero is A GUI utility to validate Wsdl / Soap using the latest WSI profile.

    @YaronNaveh

    What's next? get this blog rss updates or register for mail updates!
  • Saturday, October 11, 2008

    Java, WCF & Web Services Interoperability (part 3 of N): It's SoapAction time

    @YaronNaveh


    So, you want to write an Axis2 web service and have .Net WCF clients too? Or maybe you already have a .Net 2.0 endpoint and want it to be consumed by WSIT? Yes, that’s possible, but there is some important stuff you should know about. Whether you are a .Net WCF, AXIS2, Metro or any other framework developer/tester – you want to stay tuned for this series.

    Arun came up with an interesting interoperability issue for WSDL's without SoapAction. SoapAction is an on-the-wire-acronym for web service operations. For example in a web service "Calculator" the operation "Add" can have a SoapAction of "http://myService/Add" (but any arbitrary name can be used). Here is how this appears in the wsdl:

    ...
    <wsdl:operation name="Add">
    <soap:operation soapAction="http://tempuri.org/Add" style="document" />
    ...



    An issue arises when no SoapAction appears: Should we use an empty SoapAction or a default one? Arun explains how this is handled in WSIT (Tango) and WCF. The conclusion is to always explicitly declare a SoapAction for all operations. If your framework generates the WSDL for you - make sure you annotate it correctly so it emit this information.

    @YaronNaveh

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

    Java, WCF & Web Services Interoperability (part 1 of N): Be XML Schema Aware

    @YaronNaveh


    So, you want to write an Axis2 web service and have .Net WCF clients too? Or maybe you already have a .Net 2.0 endpoint and want it to be consumed by WSIT? Yes, that’s possible, but there is some important stuff you should know about. Whether you are a .Net WCF, AXIS2, Metro or any other framework developer/tester – you want to stay tuned for this series.

    This first post deals with XML schema, what you can do with it and – more importantly – what you shouldn’t do with it. I’m not going to preach you on service-first vs. wsdl-first approaches –
    others wrote some good posts on it. I am going to recommend you on some good habits no matter which approach you take.

    DO be aware of your schema
    If you are a wsdl-first type of developer then the schema is the first item you get to be aware of. But even if you prefer working with annotated classes: Be aware of how the different language types and annotations affect your wsdl – you don’t want to find yourself with a non-interoperable wsdl at a late stage.

    DO be aware of schema subsets
    This one is more for Java developers wanting to build service that interoperate with WCF. Microsoft has decided that WCF will support only a subset of the XML schema as a first class member. The main reason is probably to promote simplicity. This subset does NOT include xsd:choice, xsd:attribute and some other very common structures. This is the WCF supported subset – be aware of it!
    One word of restriction is required: Even if you use unsupported schema constructs in your wsdl WCF proxies have a “backward compatible” mode and they “downgrade” themselves to the .Net 2.0 supported schema subset which is larger. So it’s not the end of the world. However for various reasons, including performance and programming model ease of use – try to stick to the WCF supported subset.

    DO ensure schema completeness
    If your schema uses some type – you have to define that type in the schema or reference another schema that defines it. In the past there were some issues with types that one framework could understand internally and that’s why it didn’t put them in the wsdl - causing other frameworks to fail. So whenever you use a system type which is not the simple integer/string/etc. you should ensure its definition appears in the wsdl. For example if you are writing a .Net 2.0 web service and one method looks like this:


    [WebMethod]
    public Guid GenerateId()


    You can notice how the wsdl contains the Guid definition:

    <s:simpleType name="guid">
    <s:restriction base="s:string">
    <s:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" />
    </s:restriction>
    </s:simpleType>


    Of course the same goes for java types such as maps and vectors – make sure they appear in the wsdl.

    DO NOT use schema types which are known to be problematic
    One example here is xsd:date and xsd:time which are not directly supported by .Net. The .Net framework treats them both as xsd:dateTime so some semantics would get loss.


    That’s it for today. Stay tuned for the following posts in this series. If you have any schema related tips feel free to drop a comment.

    @YaronNaveh

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

    Cryptic WCF error messages (part 2 of N)

    @YaronNaveh


    We continue our journey in WCF error messages. Today’s error is actually somehow related to the first cryptic WCF error message. The use case here again includes X.509 certificates. This time we are just using xml digital signature without encryption. When we run our client we get the following error:


    Cannot resolve KeyInfo for verifying signature: KeyInfo 'SecurityKeyIdentifier
    (
    IsReadOnly = False,
    Count = 1,
    Clause[0] = X509IssuerSerialKeyIdentifierClause(Issuer = 'CN=Root Agency', Serial = '-52580476043899823005482728065021010894')
    )
    ', available tokens 'SecurityTokenResolver
    (
    TokenCount = 1,
    TokenEntry[0] = (AllowedReferenceStyle=External, Token=System.IdentityModel.Tokens.X509SecurityToken, Parameters=System.ServiceModel.Security.Tokens.X509SecurityTokenParameters:
    InclusionMode: Never
    ReferenceStyle: Internal
    RequireDerivedKeys: False
    X509ReferenceStyle: Any)
    )
    '.


    Since we already know how to configure wcf tracing we did just that on the server. Surprisingly enough the trace contained no error! Furthermore, the message logs in the server shows that the server got a valid request and even sent the correct response. Hmmm…
    The next step is to configure tracing and logging at the client. The logging seems fine and the trace log shows us the same exception “Cannot resolve KeyInfo…”.

    What happened is exactly the same as with last time: The client and the server are not using matching X.509 certificates. As suggested there, you should verify the correctness of the X.509 references in web/app.config. If that doesn't help - remove and reinstall the relevant certificates from the windows certificate store.

    @YaronNaveh

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