Pages

Tuesday, June 14, 2011

wcf.codeplex.com is the place where most of the wcf action happens at these days. If you have been following it recently you have seen a lot of activity around Rest and Http. As of yesterday Soap officially joins the codepex party. Microsoft has just released the WCF Express Interop Bindings - a new Visual Studio extension for Soap web services interoperability. If you use Wcf this matters to you!

What did Microsoft release yesterday?

Web services interoperability is always a pain. When security is involved it is usualy more then a casual 'oouch'. Yes, WsHttpBinding has a specific permutation of settings which can interoperate with Oracle web logic. And I know a lot of people who have tried to find that permutation in a brute force manner. Mostly doing this is a waste of time which we prefer to invest in more productive areas.

So here's the idea behind yesterday's shipping: We now have a new binding, WebLogicBinding, which only allow us to configure settings which are interoperable with web logic. So all settings are interoperable! We also have bindings for web sphere, axis2 (wso2) and metro (wsit / glassfigh / tango).
In addition we got a nice wizard on top of Visual Studio's new project dialog which allows us to easily author interoperable services using these bindings.

But don't we already have WS-Policy for interoperability?

WS-Policy helps clients to generate proxies which complies with the service requirements as expressed by the Wsdl. The express bindings solves a prior problem: How to write from the first place a service which a specific client platform can support? Once we write such a service its Wsdl will contain the WS-Policy pixy dust so that the client can auto-configure itself.

Nice... I'll take two!
You can take four: MetroBinding, WebSphereBinding, WebLogicBinding and Wso2InteropBinding.
Take them from here.

Tutorial - WCF and Metro interop

Let's see why web services interoperability just got a whole lot easier.
We'll create a WCF service with mutual x.509 certificates in the message level and consume it with a Metro client.

1. Prepare the environment
You need VS 2010 and the express bindings. After you extract the bindings zip simply execute bin\Microsoft.ServiceModel.Interop.Extension.vsix which will install it on VS.

2. Create a new service

In VS create a new project. Note how the Wcf node now contains a new project type "Express Interop Wcf Service Application":

Choose that project type.

3. Configure the express binding wizard

A few moments after creating the project you will see the wizard.
First choose the platform our clients will use - Metro, this time.

Now we need to configure our security requirements. Choose "mutual certificate" which means both client and server will present an x.509 certificate in the message level. It also implies encryption and digital signature (in this case). To keep it simple we omit the secure conversation.

Next in the advanced settings use the Basic128 algorithm since it is the one Metro supports by default (for Basic256 a patch needs to be applied).

Finally configure the certificate.

I recommend to use this certificate (password: adminadmin):

Now run the service. This is a web site project so it will open the documentation page with the Wsdl link. Make sure to have the Wsdl url handy since we will use it in a moment.

Now we want to configure Metro.

1. Set up the environment

You should have NetBeans 7 (or higher), though NetBeans 6.7 also worked for me.

2. Create a new project of type Java Application:

Any of the default settings are fine:

3. Right click the package in the project view and add a new "web service client":

Now is a good time to paste that Wsdl url:

4. The service reference is now in the project view so right click it and edit the Web Service Attributes (similar to the Wcf configuration... just very different :):

5. This step is a workaround if your NetBeans version ships with Metro 2.0 (which is the case for NetBeans 7). See below how to know if you need it.

We can see that Metro had automatically identified that client and server certificates are required. This was due to the WS-Policy in the Wsdl.

Before we continue we need to do some trick. NetBeans 7 ships with Metro 2.0 which has a bug with certificates. In favor of those who reach this post via a search engine this is the error message:

To solve this you need to download Metro 2.1 (or higher). For now just extract it to some folder.

Now as part of this workaround check the "use development defaults" drop down in the quality attributes dialog you opened in step 4. Also approve any message you are prompt with.

Click Ok to close the dialog.

In the project pane expand the libraries node. It should look like this:

This workaround applies to version 2. If you see another version (even smaller) no need for this. What you need to do is delete all the references to Metro jar files (don't delete the jdk though). Instead of them right click the "libraries" node, choose "add jar/folder..." and choose the jar files in metro\bin folder from the metro 2.1 zip you just extracted. Add all jar files in that folder. The libraries node will now look like this:

6. We are now ready to do the actual configuration. Open again the web service quality attribute form as you did in step 4. Uncheck the "use development defaults" check box. Now configure the keystore and trust store. I recommend to use this java key store file:

Open "keystore..." and "Truststore.." each in its turn and do the below.
Set the path to the .jks file you extracted form the certificates file above, set the password to "adminadmin", and click "load alias". The alias for the key store is xws-security-client and for the trust store is xws-security-server.

7. Now we need to write the client code.

Since most of my readers are .Net developers let's see if we can pull this one out without any Java coding at all.

Drag the GetData node from the project pane to the main() method. It should now look like this (depending on the netbeans version):

44
comments:

In our case, we have a wcf relying party that uses ws2007FederationHttpBinding and a token issuer uses ws2007FederationHttpBinding (token as credential) and ws2007HttpBinding (username/pwd as credential). How do we make those interoperable?

@scott - if you look for concrete guidance here are two good ones by Jesus Rodriguez:

Wcf & WebLogic federation:

http://msdn.microsoft.com/en-us/netframework/gg413253.aspx

Wcf & WebSphere federation:

http://msdn.microsoft.com/en-us/netframework/gg413262.aspx

There is nothing in your configuration which prevents interoperability, though due to the richness of the underlying ws-* standards you might need to fine tune some settings, depending on the platforms you need to interoperate with.

thanks for this post.i got the same error:At least one security token in the message could not be validated.in netbeans,now after all trials its my dream to see that a java client webservice runs without a bug.

im back,here is my stack elements:At least one security token in the message could not be validated.com.sun.xml.ws.fault.SOAP12Fault.getProtocolException(SOAP12Fault.java:229)com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:126)com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:123)com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:93)com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:144)$Proxy40.getData(Unknown Source)javaapplication15.JavaApplication15.getData(JavaApplication15.java:34)javaapplication15.JavaApplication15.main(JavaApplication15.java:19)

i got my certificate all setup,and its been running by iis,i got this issue and im totally trapped,any help would be much appreciated.thanks.

The X.509 certificate CN=localhost 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.

finally i used ur certificates and i got that "The EncryptedKey clause was not wrapped with the required encryption tokenmessage" u already posted about that it is because the certificates are not match.i really did exactly what u told and showed in ur post.plz take a time to see what is wrong in the ur post plzzzz...im on a real hard deadline for my WSIT project.really thanks.

sorry i was wrong in my last comment,now i did all the things u said and i got this message in wcf trace:

The X.509 certificate CN=xwssecurityclient, OU=SUN, O=Internet Widgits Pty Ltd, S=Some-State, C=AU 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 could not be built to a trusted root authority.

this causes an exception in netbeans:At least one security token in the message could not be validated.

i have imported xwssecurityclient.pfx into currentuser/personal/certificates and also into xwssecurityclient.pfx into currentuser/trustedpeople/certificates

I'm struggling with this exact same scenario. My WCF 4.0 service is running inside IIS 6 and we could also use IIS 7.

The client is running Metro inside of IBM Websphere!~@).

Our client told me this: our web framework is developed exclusively using IBM WebSphere. So I have deployed the Metro stack into our IBM WebSphere (and Eclipse) environments....which had many side effects, including the need to disable the IBM web services stack in order to make Metro work.

Anyway, after creating the binding with the MS extension tool, I see the underlined in red in VS and an error:

The element 'bindings' has invalid child element 'metroBinding'. List of possible elements expected: lists all valid binding types... Does this matter at run-time? I also can't pull up the config in the Service Config Editor.

Also, currently I am using one of your custom bindings with success for my .Net client. We have a SSL site and using Username in clear text. Should I use the binding created by the MS tool or convert it back to a custom binding?

[10/18/11 14:56:18:957 EDT] 00000025 SystemOut O 14:56:18,956 FATAL GenericWorker run javax.xml.ws.soap.SOAPFaultException: The message could not be processed. This is most likely because the action 'https://www.upmchp.com/CORETransactions/RealTimeTransaction' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.at com.sun.xml.ws.fault.SOAP12Fault.getProtocolException(SOAP12Fault.java:229)....

With the metroBinding, I get this error: Could not find a base address that matches scheme http for the endpoint with binding metroBinding. Registered base address schemes are [https].

how to generate the Client and server certificates?When I use SelfSigned Certificates and exported as .pfx and deployed in Localmachine - all fine but when I see details of certificates - it shows an Error mark.

Self signed certificates are not trusted by default. You should get a certificate from a certificate authority that you trust, or create your own authority and put its cert in the trusted root store. You can also put the self signed cert there to make it trusted

Hi Yaron,Thanks for your response. I am currently testing at my DEV, so when it goes to UAT or PRD I can raise request to get it. between How to Generate it? As you mentioned: "create your own authority and put its cert in the trusted root store"

The words "brute forcing" the correct settings really hit a string. I'm currently trying hard to make WCF interop with some jboss based WS Service implementation, but no success until now.It needs mutually signed (not encrypted) message on an SSL connexion.

I'm stuck on the following :- If I set Message protection, my message are encrypted which I don't want : ProtectionLevel.Sign seems to be set on the interface, but my interface is auto-generated from the WSDL and I don't want to change the generated code. So how do I change it on the custom binding instead ?- What's more if I set Message protection, the binding refuses a https URL. Is there a way to override that ? I tried to use a local stunnel, but it's not a great solution- If I set CertificateOverTransport, the returned message is signed and I get the error "Cannot find a token authenticator for the 'System.IdentityModel.Tokens.X509SecurityToken' token type. Tokens of that type cannot be accepted according to current security settings.". But allowSerializedSigningTokenOnReply changes nothing, I still have the error. Maybe I can just write a custom message encoder to remove that header, but I don't really like the option (and would like to find some code sample if I decide to do it).

Thanks you for the answer that's encouraged me to try some more, although it's not our top priority so I can't spend too much time on it.

The exchange works in MutualCertificate mode, by adding a node

to the binding and also

However I'm stuck again !The value of the endpoint gets used to verify both the SSL certificate, and the one that signs the response, and it's not the same name. If I put a dns value to match the SSL cert, it fails when verifying the answer, and if I put the name of the signature cert in it, it fails when verifying the identity at the SSL level.I could send you the settings, and request/response, but I'm not sure it brings much at this stage, I believe you already have the important info, WS Security with mutual certificates and signature only, and HTTPS with a different certificate.

To sum up :- Switch to custom binding, using settings compatibles with BasicHttpBinding (your online converter is useful there)- Set MutualCertificate authentication mode- Set https transport <httpsTransport requireClientCertificate="false" />- Set signature only <context protectionLevel="Sign" />- Set the <identity> node of the endpoint to the identity used in message signature- Disable globally the SSL server certificate name verification by modifying the ServicePointManager.ServerCertificateValidationCallback implementation

great it is working.I need some technical support to consume oracle web logic web service which is hosted at client side and our environment is Microsoft .net .I have used WSE 3.0 or wcf to consume the service but the result is failure .The weblogic service security is maintained with user token and x509 certificateThe webservice link is http://XXX.XXX.XXX.XX/MMS/MMSService?wsdl and the client provides me the client code how they are consuming their service in weblogic environment .

Please help me any type of compatibility or inter operability between .net and oracle weblogic service as per link.http://docs.oracle.com/cd/E12839_01/web.1111/e13759/interop.htm#BABFCJCD[^]and client code like http://stackoverflow.com/questions/11823849/consume-java-weblogic-web-service-having-usernametoken-and-client-certificate-in[^]

Your example on how to use Netbeans/Metro was great. Its saved me a lot of headaches. I tried to use what I'd learned on a real world WCF webservice and I came across an issue that when calling a method and the body had a \r\n in it an exception was thrown. With the \r in the body Metro and .NET were computing different digests. Has anyone come across this? Can I deal with it on the Java Client side, or is it the .NET web services responsibility?

In regards to my earlier post regarding exceptions thrown when a \r is in the message body (SEVERE: WSS1717: Error occurred while doing digest verification of body/payload)it looks to be a known Metro client WCF service issue. Unfortunitely from what I've been finding on the web its WCF's fault(or so the Java people claim). Is there any way to ignore the exception? ie. Ignore the digests not matching up?

You cannot customize the way Wcf handles signatures. Assuming the message is only signed and not encrypted, you coul tell Wcf to ignore the signature all together, and then either do the validation yourself or decide not to do it.

maybe you can replace the \r\n values in the body with some other char, and put them back in the server. Otherwise the only way I see is to turn off security in the wcf side all together and do the validaiton yourself or not do it.

I've reported to problem to the owner of the web service. The other clients for this service are all .Net so of course they don't have any problems. Shame there isn't some setting to ignore whether or not the digests match up on the client side.