Tag Archives : WSE


New post under consideration

Hi All.

Engineering FlowchartI’m debating a new article.

I’m currently debating whether to spend some time documenting an interesting solution to a fairly esoteric scenario.  I’m not sure if it is worth the investment (in my time), so I’m going to throw it open to the community. 

Give me feedback – if you have an interest in seeing this solution, please leave a comment.  The only reason I mention this is because the solution is really quite interesting, and a good lesson in the rarer binding types (and message & transport security) in Windows Communication Foundation (WCF).

Here’s the premise:

We have a .NET 2.0 client (which can not be upgraded to 3.5 or 4.0) which must consume a web service by providing a Web Service Extension (WSE) 3 policy file – which stipulates a separate set of credentials (username/password/domain) for authentication in a downstream legacy system.

Presently, this client calls a series of legacy ASMX services (also .NET 2.0).  However, there is a desire to upgrade these services to WCF (for more widespread use) and so we can take advantages of .NET 4.0 in the service implementation and beyond.  The challenge is to provide the same functionality (policy file attached to the transport) for later authentication. 

The information would be transmitted by HTTPs or via HTTP under a VPN (so, ultimately, encrypted).  This is obviously a fairly intriguing paradigm, made more interesting by the prospect of actually not using the WSE3 policy information for handshake authentication.

The original design, from my understanding, was to make the passing of credentials transparent to the service calls themselves (hence, not passing username, password and domain per service call explicitly).  I could be wrong about that, but in any case this is the scenario we have today.

Here’s where you fit in:

So, I repeat – who’d be interested in seeing the solution?  Please leave a comment to indicate an interest.  Depending on how much interest there is, I’ll put together both a long article and a sample, demonstrative, solution.

Cheers, R


WCF Services with WSE 3.0 compatible bindings

Hi There,

So chances are if you’ve read my subsequent posts, you’ll get the feeling that I’m working with some legacy web service applications.  You’d be right, and the challenge of Web Service Extensions (WSE) 3.0 is figuring out how to upgrade them to WCF (.NET 3.5/4.0) without harming the legacy clients who consume them.  We’ll call it a 1-2 punch combination – update the services, then we can worry about the consuming applications.

However.. there are a few challenges.  As it turns out, you don’t need to wrap WCF services with a WSE web application as I first suspected.  This will work, but it gives you an extra set (of legacy) web services and you don’t really need an extra set of bindings and configuration which could cause you trouble down the stretch.

The solution is somewhat straightforward, in that WCF (in .NET 3.5/4.0) supports WSE 3.0 compatible bindings.  Trouble is, you have to use a custom binding, and it has a tendency to require a secure transport (out of the box) which can throw you.

Here’s what MSDN has to say about using a backwards compatible binding with WCF:

To enable a WCF service to interoperate with WSE 3.0 clients

Define a custom binding for the WCF service.

To specify that the August 2004 version of the WS-Addressing specification is used for message encoding, a custom binding must be created.

  1. Add a child customBinding Element to the <Bindings> of the service’s configuration file.
  2. Specify a name for the binding, by adding a binding element to the customBinding Element and setting the name attribute.
  3. Specify an authentication mode and the version of the WS-Security specifications that are used to secure messages that are compatible with WSE 3.0, by adding a child Security element to the binding element.
    To set the authentication mode, set the authenicationMode attribute of the Security element. An authentication mode is roughly equivalent to a turnkey security assertion in WSE 3.0. The following table maps authentication modes in WCF to turnkey security assertions in WSE 3.0.

    WCF Authentication Mode = WSE 3.0 turnkey security assertion

    AnonymousForCertificate  = anonymousForCertificateSecurity

    Kerberos = kerberosSecurity

    MutualCertificate = mutualCertificate10Security*

    MutualCertificate = mutualCertificate11Security*

    UserNameOverTransport = usernameOverTransportSecurity

    UserNameForCertificate = usernameForCertificateSecurity

    * One of the primary differences between the mutualCertificate10Security and mutualCertificate11Security turnkey security assertions is the version of the WS-Security specification that WSE uses to secure the SOAP messages. For mutualCertificate10Security, WS-Security 1.0 is used, whereas WS-Security 1.1 is used for mutualCertificate11Security. For WCF, the version of the WS-Security specification is specified in the messageSecurityVersion attribute of the Security element.

    To set the version of the WS-Security specification that is used to secure SOAP messages, set the messageSecurityVersion attribute of the Security element. To interoperate with WSE 3.0, set the value of the messageSecurityVersion attribute to WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10.

  4. Specify that the August 2004 version of the WS-Addressing specification is used by WCF by adding a textMessageEncoding element and set the messageVersion to its value to Soap11WSAddressingAugust2004.

    ms730049.note(en-us,VS.90).gifNote: When you are using SOAP 1.2, set the messageVersion attribute to Soap12WSAddressingAugust2004.

  1. Specify that the service uses the custom binding.

    1. Set the binding attribute of the Service Endpoint element to customBinding.
    2. Set the bindingConfiguration attribute of the Service Endpoint element to the value specified in the name attribute of the binding element for the custom binding.

Example:

The following code example specifies that the Service.HelloWorldService uses a custom binding to interoperate with WSE 3.0 clients. The custom binding specifies that the August 2004 version of the WS-Addressing and the WS-Security 1.1 set of specifications are used to encode the exchanged messages. The messages are secured using the AnonymousForCertificate authentication mode.

<configuration>
  <system.serviceModel>
    <services>
      <service 
        behaviorConfiguration="ServiceBehavior" 
        name="Service.HelloWorldService">
        <endpoint binding="customBinding" address=""
          bindingConfiguration="ServiceBinding"
          contract="Service.IHelloWorld"></endpoint>
      </service>
    </services>

    <bindings>
      <customBinding>
        <binding name="ServiceBinding">
          <security authenticationMode="AnonymousForCertificate"
                  messageProtectionOrder="SignBeforeEncrypt"
                  messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                  requireDerivedKeys="false">
          </security>
          <textMessageEncoding messageVersion ="Soap11WSAddressingAugust2004"></textMessageEncoding>
          <httpTransport/>
        </binding>
      </customBinding>
    </bindings>
    <behaviors>
      <behavior name="ServiceBehavior" returnUnknownExceptionsAsFaults="true">
        <serviceCredentials>
          <serviceCertificate findValue="CN=WCFQuickstartServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName"/>
        </serviceCredentials>
      </behavior>
    </behaviors>
  </system.serviceModel>
</configuration>

So after defining your WCF services, instead of using a basicBinding or a wsHttpBinding, all you need to do is define a customBinding, like the one below:

<!– WSE 3 compatible binding –>

      <!– http://msdn.microsoft.com/en-us/library/ms730049%28v=VS.90%29.aspx –>

     
      <customBinding>

        <binding name="customWseBinding"> 
         <security messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"

                    authenticationMode="UserNameOverTransport"

                    allowInsecureTransport="true">

          </security>

          <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />

         <httpTransport authenticationScheme="Anonymous" />          
        </binding>     
      </customBinding>

Now, assuming all your other settings are set correctly, you might get excited when the page.. almost.. loads:

image

However, what is this?

Error: Security policy export failed. The binding contains a TransportSecurityBindingElement but no transport binding element that implements ITransportTokenAssertionProvider. Policy export for such a binding is not supported. Make sure the transport binding element in the binding implements the ITransportTokenAssertionProvider interface. ----> System.InvalidOperationException: Security policy export failed. The binding contains a TransportSecurityBindingElement but no transport binding element that implements ITransportTokenAssertionProvider. Policy export for such a binding is not supported. Make sure the transport binding element in the binding implements the ITransportTokenAssertionProvider interface.

Not what we were expecting?  Basically, httpTransport doesn’t implement the ITransportTokenAssertionProvider which is what is being expected by the customBinding.  To work around this you have to, unfortunately, implement your own custom transport.  It’s nasty, but it works.

To take a look at the classes you’ll need, please read this article or this article.

After implementing the custom handler, the binding looks like this:

<customBinding>

        <binding name="customWseBinding">

          <security messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"

                    authenticationMode="UserNameOverTransport"

                    allowInsecureTransport="true">

          </security>

          <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" />

          <!–<httpTransport authenticationScheme="Anonymous" />–>

          <CustomHttpTransport authenticationScheme="Anonymous" />

        </binding>     
      </customBinding>

Which results in the following screen:

image

 

References

How to: Configure WCF Services to Interoperate with WSE 3.0 Clients

http://msdn.microsoft.com/en-us/library/ms730049%28v=VS.90%29.aspx

http://social.msdn.microsoft.com/forums/en-US/wcf/thread/ea0ff7b6-12c4-487d-a983-c07e06260acf/


WSE 3.0 Support in Visual Studio 2010

Sometimes, for various reasons, we come across projects or solutions we have to maintain to our chagrin.  We have an application which runs on .NET 2.0 and can’t be upgraded to 3.5 or beyond.  This application consumes web services published via the old ASMX services, and uses Web Service Extensions 3.0 (WSE 3.0) – the precursor to Windows Communication Foundation (WCF).

If you are in the same position, and you have upgraded your solution to Visual Studio 2010 (but are still targeting .NET 2.0), you might find that, by default, updating those web references causes the base class to change from WebServicesClientProtocol to SoapHttpClientProtocol.

This is by design, as it is anticipated that all web services be upgraded to WCF, however sometimes this causes widespread destruction and it’s easier and more convenient to just be able to use the previous importer.  This can be done in Visual Studio 2010, but it is somewhat nasty.

Here is a step by step guide to enabling WSE 3.0 references in Visual Studio 2010:

1. Close Visual Studio 2010
2. Download and Install WSE 3.0 (if you haven’t already)
     a. http://www.microsoft.com/downloads/en/details.aspx?FamilyID=018a09fd-3a74-43c5-8ec1-8d789091255d
3. In Explorer, open the following folder:

a. C:\ProgramData\Microsoft\MSEnvShared\Addins (or)
b. C:\Documents and Settings\All Users\Application Data\Microsoft\MSEnvShared\Addins


4. Locate the following file:
     a. WSESettingsVS3.Addin
5. Open the file in Notepad
6. Replace <Version>8.0</Version> with <Version>10.0</Version>, then save
7. In Explorer open the following folder:
    a. C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE
8. Locate the following file:
   
a. devenv.exe.config
9. Open the file in Notepad
10. Add the following at the end of the file (before the </configuration>) and save:

<system.web>
<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter,
Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
</webServices>
</system.web>

11. Open Visual Studio 2010
12. In Tools -> Options -> Environment->Add-in/Macros Security ensure that this entry exists:
       a. %APPDATA%\Microsoft\MSEnvShared\Addins
13. Update web references

References:

http://stackoverflow.com/questions/433062/wse-client-project-keeps-reverting-webservicesclientprotocol-to-soaphttpclientpro
http://www.junasoftware.com/blog/how-to-use-wse-3-in-visual-studio-2010.aspx
http://www.junasoftware.com/blog/how-to-use-wse-3-in-visual-studio-2008.aspx