Tuesday, April 15, 2008

Secure Web Services Interoperability using X.509 Certificate Token Profile (AXIS 1.4, WSS4J 1.5.3, dotnet 2.0, WSE 3.0 )

Dear reader,

I would like to share with you that I was able to sucessfully implement the interoperability (Java - Microsoft world) using the X.509 Certificate Token Profile.


The goal was to develop a secured web service in java with the corresponding secured java and Microsoft clients.


Tasks:


  • write java secured web service (server side) using apache axis 1.4 and wss4j 1.5.3 based on x509 v3 certificates and the java key store format (jks).

  • the java keystore is implemented using the java keytool

  • the java secured client and the related dotnet client (using .net 2.0 and wse 3.0) are working fine with the java secured web service based on the X.509 Certificate Token Profile.

  • I succesfully set up a CA (certification authority), set up properly the jks and finally from the jks I sucessfully prepared the necessary pfx (PKCS #12, using OpenSSL) certificate for the secured dotnet client to interoperate with the java secured web service.

  • The set up is working fine!

This task couldn't be done without the work from people of Axis 1.4 and wss4j that I would like to thank.Also of the blog written by Erlend and his answers.
Anne Thomas Manes for answering some of my questions in the newsgroups of Axis about the interoperability in the wsdl files and Werner Dittman for the provided answers in the wss4j newsgroup!


Big Thanks and HAPPY AXIS :-)!

Conclusion: It is possible to set up a java secured web service using the keystore (jks). It is possible to develop a microsoft client using the framework dotnet 2.0 and the web service enhancements 3.0 (WSE 3.0). It is possible to extract the clients certificates from the java keystore using OpenSSL into the format pfx (PKCS #12) in order that the microsoft client communicate with the secured java service using the x509 certificate version 3. Hope this helps.


PS: This book about Apache Axis 1.4 help me also to understand web services.
Please note that I have any interest/relationship/benefit with the author of the book.

Snapshots

my key files


windows keystore



client pfx certificate

client pfx certificate (please note the private key)

Secured Java Client


Secured dotnet client


TCP monitor (request from java secured client to java secure server)


Soap monitor (dotnet secured request to the java secured web service)

17 comments:

Paul said...

Hi Jose,
If you have posted the code to achieve this goal, would you be so kind as to post a link where one could take a look? I would be very obliged.

Regards,
Paul Dotsenko
pdotsenko at gmail dot com

Jose Ferreiro said...

Hello Paul,

Please look at the article from Erlend located at http://erlend.oftedal.no/blog/?blogid=12

Kind regards,

José Ferreiro

Jose Ferreiro said...

TESTING THE CLIENTS WITH DIFFERENT LOCAL TIME ZONES vs SEVER LOCAL TIME ZONE


I started developing a secure web service in my development computer.
However when I deployed the application (in another server[JBoss]) to simulate different clients connecting to the web service with different LOCAL TIME ZONES, things went bad...

Problems with TIMESTAMP validation...

I got error the following error depending on the tested client (either dotnet or java):

In Microsoft
[dotnet framework 2.0, WSE 3.0]
WSE065: Creation time of the timestamp is in the future. This typically indicates lack of synchronization between
sender and receiver clocks.

or for java
[Axis 1.4, wss4j 1.5.3]
Exception: WSDoAllReceiver: security processing failed; nested exception is:
org.apache.ws.security.WSSecurityException: An error was discovered processing the < wsse:Security > header. (WSSecurityEngine: Invalid timestamp The security semantics of message have expired)

The problems are due that the two clocks in the clients and the server are not synchonized.

JAVA World: WSS4J - Use the timeToLive parameter in the handler to resolve this problem [1] [2].

MICROSOFT World: WSE 3.0 - Use the tags timeToleranceInSeconds and defaultTtlInSeconds in the app.config file of the web service in your project (illustration follows with the corresponding xml tags) [3]

< configuration >
< microsoft.web.services3 >
< security >
< timeToleranceInSeconds value = "3600" / >
< defaultTtlInSeconds value = "3600" / >

[1] - http://wiki.apache.org/ws/FrontPage/WsFx/wss4jFAQ#time
[2] - http://ws.apache.org/wss4j/apidocs/org/apache/ws/security/handler/WSHandlerConstants.html#TTL_TIMESTAMP
[3] - http://msdn.microsoft.com/en-us/library/ms824668.aspx

ssn said...

gud post.
helpful links

Jose Ferreiro said...

The example has been build using WSDL first approach.

Jose Ferreiro said...

Deployment of web service containing complex data types

Chances are that if you are using Axis 1.4 and you deploy your web services deployment descriptor file .wsdd when you will visit the wsdl through the following page http://localhost:8080/axis/servlet/AxisServlet
the the following error will show up.


AXIS error

Sorry, something seems to have gone wrong... here are the details:

Fault - makeTypeElement() was told to create a type "{http://your_namespace}>>complexType>element", with no containing element

AxisFault
faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.generalException
faultSubcode:
faultString: makeTypeElement() was told to create a type "{http://your_namespace}>>complexType>element", with no containing element
faultActor:
faultNode:
faultDetail:
{http://xml.apache.org/axis/}hostname:yourhostname


This is a known bug from Axis 1.x

In order to solve it proceed as follows. You should use named schema types in your data types wsdl part.


< element name="Principal" >
< complexType>
< sequence >
< element name="Person" minOccurs="1" maxOccurs="unbounded" >
< complexType>
< attribute name="firstName" type="string" / >
< attribute name="lastName" type="string" / >
< /complexType >
< /element >
< /sequence >
< /complexType >
< /element >

Changed it to:

< element name="Principal" >
< complexType>
< sequence >
< element name="Person" minOccurs="1" maxOccurs="unbounded" type="impl:Person" / >
< /sequence >
< /complexType >
< /element >


< complexType name="Person" >
< attribute name="firstName" type="string" / >
< attribute name="lastName" type="string" / >
< /complexType >

Hope this helps!
Regards,

Jose Ferreiro

Jose Ferreiro said...

Google tips to work with certificates for you development box:

http://code.google.com/support/bin/answer.py?answer=71864&topic=11369

siva said...

Hi Jose,

I am siva, i am developing a javawebservice and .net client with webservices security, my .net client configuration is missleading. kindly provide me source code of this post so that i will verify my code .

Thanks in Advacne
-------------
Siva kumar

Jose Ferreiro said...

Hi Siva,

Are you having the same configuration as I am? Please see on my post above the link to Erlend's blog . He provides the .NET configuration where the key algorithms WSE are used in the web.config file. As well as the policy using mutualCertificate10Security and not mutualCertificate11Security .
In order to make work your configuration you need understand the keystores ( windows and java ). There is a bunch of information at Erlend's blog . You may help yourself by employing built in certificates from WSS4J in the folder interop. This is within the zip file of WSS4J. Unfortunately the code I used for this post has been extensible modified and I do not have it so anymore. Try with a very simple example and then you should proceed step by step. Good luck Siva.

siva said...

Hi Jose,
Thanks for your reply, now i am to decrypt the message which was coming from request, but while processing the actions i am getting the following error:
ERROR org.apache.axis2.engine.AxisEngine - WSDoAllReceiver: security processing failed (actions mismatch)
org.apache.axis2.AxisFault: WSDoAllReceiver: security processing failed (actions mismatch)
at org.apache.rampart.handler.WSDoAllReceiver.processBasic(WSDoAllReceiver.java:215)
at org.apache.rampart.handler.WSDoAllReceiver.processMessage(WSDoAllReceiver.java:56)
at org.apache.rampart.handler.WSDoAllHandler.invoke(WSDoAllHandler.java:72)
at org.apache.axis2.engine.Phase.invoke(Phase.java:318)

My .net configuraton is as follows
app.config





































Thanks in Advance
----------
Siva

Jose Ferreiro said...

Hi Siva,

According to your fault you are using Axis2. In the example I did I am uisng Axis 1.x. The architecture of both implementations (Axis 1.x versus Axis2) is completely different. If I understood well with Axis2 you are using Rampart module which is using WSS4J. You need to provide the correct parameters to Rampart module. I hope this helps. Regards Siva and I take the opportunity to wish you a happy new year 2010. José Ferreiro

siva said...

Pleas find the below config file

App.config:

< client >
< endpoint address="http://localhost:8081/server/services/HelloWorld"
behaviorConfiguration="ClientCertBehavior" binding="customBinding"
bindingConfiguration="JavaInterop" contract="ServiceReference1.HelloWorldPortType"
name="HelloWorldHttpSoap12Endpoint">
< identity >
< dns value="YALAMANCHILI" />
< /identity>
< /endpoint>
< /client>
< bindings>
< customBinding>
< binding name="JavaInterop">
< security defaultAlgorithmSuite="Basic128Rsa15" allowSerializedSigningTokenOnReply="true"
authenticationMode="MutualCertificate" requireDerivedKeys="false"
securityHeaderLayout="Lax" includeTimestamp="true" messageProtectionOrder="EncryptBeforeSign"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
< issuedTokenParameters keyType="AsymmetricKey" />
< localClientSettings detectReplays="false" />
< secureConversationBootstrap defaultAlgorithmSuite="Basic128Rsa15"
allowSerializedSigningTokenOnReply="true" authenticationMode="MutualCertificate"
requireDerivedKeys="false" securityHeaderLayout="Lax" includeTimestamp="true"
messageProtectionOrder="EncryptBeforeSign" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
< issuedTokenParameters keyType="AsymmetricKey" />
< /secureConversationBootstrap>
< /security>
< httpTransport authenticationScheme="Anonymous" />
< /binding>
< /customBinding>
< /bindings>


< behaviors>
< endpointBehaviors>
< behavior name="ClientCertBehavior">
< clientCredentials>
< clientCertificate findValue="f1 88 d8 95 76 76 5b be 74 53 90 92 fc cf 16 e0 67 5e 4d 34"
storeLocation="CurrentUser" storeName="My" x509FindType="FindByThumbprint" />
< serviceCertificate>
< defaultCertificate findValue="d4 79 bc 17 94 3a 3c 14 a1 a2 1f c7 ba b7 a7 3e 08 1b 0a 8d"
storeLocation="CurrentUser" storeName="My" x509FindType="FindByThumbprint" />
< authentication certificateValidationMode="None" revocationMode="NoCheck"
trustedStoreLocation="LocalMachine" />
< /serviceCertificate>
< /clientCredentials>
< /behavior>
< /endpointBehaviors>
< /behaviors>

Thanks
---------
Siva

Jose Ferreiro said...

Dear Siva,

You should also have a file named wse3policyCache.config. Are you suing WSE 3.0 ?

See here below the app.config file I had. Please use the trace utility into Visual Studio to trace the output and incoming message.












http://machineName:8080/axis/services/XYZW

Jose Ferreiro said...

< configuration >
< configSections >
< section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" / >
< sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
< section name="WSE_Client_Test_Jose_FERREIRO.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
< /sectionGroup>
< /configSections>
< applicationSettings>
< WSE_Client.Properties.Settings>
< setting name="WSE_Client1_ExampleSecuredService" serializeAs="String">
< value>http://machineName:8080/axis/services/XYZW

< /WSE_Client.Properties.Settings>


< security>

< timeToleranceInSeconds value="3600" />

< binarySecurityTokenManager>
< add valueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">
< keyAlgorithm name="RSA15" />
< /add>
< /binarySecurityTokenManager>

< securityTokenManager>
< add type="Microsoft.Web.Services3.Security.Tokens.EncryptedKeyTokenManager, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="http://www.w3.org/2001/04/xmlenc#" localName="EncryptedKey">
< keyAlgorithm name="AES128" />
< /add>
< /securityTokenManager>
< /security>
< diagnostics>
< trace enabled="true" input="PathToYourTraceFile\\traces\\InputTrace.webinfo.xml" output="PathToYourTraceFile\\traces\\OutputTrace.webinfo.xml" />
< detailedErrors enabled="true" />
< /diagnostics>
< policy fileName="PathToYourPolicyFile\\wse3policyCache.config" />
< /microsoft.web.services3>
< /configuration>

Sam said...

Hello Jose and Others,
Could anyone please share any step-by-step guide for achieving the security integration between Java (Axis 1.4)and .Net using WSS4J and WSE?

I am unable to acheive it. I am looking for step-by-step tutorial on how to accomplish it.

Regards,
Sam

Sam said...

Hello Jose and Others,
Do you have any step-by-step guide that you follwed to achieve interation between Java (Axis 1.4)and .Net using WSS4J and WSE?

I am unable to acheive it. I am looking for step-by-step tutorial on how to accomplish it.

Regards,
Sam

Jose Ferreiro said...

Hello Sam,

Unfortunately I do not have such a tutorial. I wrote this article by own interest to show that it is possible to achieve interoperability between Java and .Net technologies. This was my ultimate goal! I will suggest you to take a look of the examples provided within the WSS4J zip file under the folder interop. This is the way I started. Good luck Sam!