Friday, January 11, 2008

Runnning the Axis2 Rampart sample "04. Message integrity and non-repudiation with signature"

pencil icon, that"s clickable to start editing the post

In a the post Rampart basic examples - how you add WS-Security to Axis2 I listed all the great examples. In this post I'll actually run one of the samples and show the generated messages. I'll take the fourth sample Message integrity and non-repudiation with signature since it's simple and adds great value with both integrity and authentication since only the sender can sign with the X509 certificate (except when the certificate is shared like here :-).

In the binary distribution of Rampart in the samples/basic folder the README.txt explains how to the run the samples:

You can use the ant build script provided here to run these samples.

Exmaple: Running sample - 01
    - Start two shell instnaces and change to the directory where this file is
    - To start the service:
      $ ant service.01
    - To run client:
      $ ant client.01

NOTE: To view the messages exchanged
    - Change the "client.port" property in the "build.xml" to an available port
          E.g. : >property name="client.port" value="9080"/<
        - Setup tcpmon ( to listen on the above
          port and to point to port 8080 (value of the service.port property)

which is quite easy, though I needed to do a couple of small fixes.

The Service (serverside)

First I wanted to start the service/server. Here's what I did to get it running:

  • setup the environment variable AXIS2_HOME. I first downloaded the Axis2 nightly to end up with a problem with running the client so I'll suggest you use Axis2 version 1.3.
  • Prepare to show messages with TCPMon by changing the client.port property:
    <property name="client.port" value="9999"/>
  • In <macrodef name="create.service.repo"> I changed:
    <copy file="${modules.dir}/${rampart.mar}" tofile="${service.repos.dir}/sample@{sample.number}/modules/${rampart.mar}" overwrite="true"/>
    <copy file="../../${rampart.mar}" tofile="${service.repos.dir}/sample@{sample.number}/modules/${rampart.mar}" overwrite="true"/>
  • Added the following fileset to the classpath on both the javac and java tasks:
    <fileset dir="../../lib">
      <include name="*.jar"/>

Then I was able to start the service (where <RAMPART_DIR> is where I unzipped Rampart-1.3):

$ ant service.04
Buildfile: build.xml


     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/service_repositories/sample04/modules
     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/service_repositories/sample04/modules
    [javac] Compiling 2 source files to <RAMPART_DIR>/samples/basic/build/temp
     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/temp/META-INF
     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/temp
     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/temp
      [jar] Building jar: <RAMPART_DIR>/samples/basic/build/service_repositories/sample04/services/sample04.aar
   [delete] Deleting directory <RAMPART_DIR>/samples/basic/build/temp
     [java] [SimpleHTTPServer] Starting
     [java] [SimpleHTTPServer] Using the Axis2 Repository <RAMPART_DIR>/samples/basic/build/service_repositories/sample04
     [java] [SimpleHTTPServer] Listening on port 8080
     [java] 2008-01-11 20:21:10,948 INFO  org.apache.axis2.deployment.ModuleDeployer - Deploying module: addressing-SNAPSHOT - file:<RAMPART_DIR>/samples/basic/build/service_repositories/sample04/modules/addressing-SNAPSHOT.mar
     [java] 2008-01-11 20:21:11,737 INFO  org.apache.axis2.deployment.ModuleDeployer - Deploying module: rampart-1.3 - file:<RAMPART_DIR>/samples/basic/build/service_repositories/sample04/modules/rampart-1.3.mar
     [java] 2008-01-11 20:21:12,036 INFO  org.apache.axis2.deployment.ServiceDeployer - Deploying Web service: sample04.aar - file:<RAMPART_DIR>/samples/basic/build/service_repositories/sample04/services/sample04.aar
     [java] 2008-01-11 20:21:12,096 INFO  org.apache.axis2.transport.http.server.DefaultConnectionListener - Listening on port 8080
     [java] [SimpleHTTPServer] Started

The client

Running the client is very much like the service, though I first got this error when I used the Axis2 nightly:

     [java] Exception in thread "main" org.apache.axis2.deployment.DeploymentException: javax/jms/BytesMessage
     [java]     at org.apache.axis2.deployment.AxisConfigBuilder.processTransportSenders(
     [java]     at org.apache.axis2.deployment.AxisConfigBuilder.populateConfig(
     [java]     at org.apache.axis2.deployment.DeploymentEngine.populateAxisConfiguration(
     [java]     at org.apache.axis2.deployment.FileSystemConfigurator.getAxisConfiguration(
     [java]     at org.apache.axis2.context.ConfigurationContextFactory.createConfigurationContext(
     [java]     at org.apache.axis2.context.ConfigurationContextFactory.createConfigurationContextFromFileSystem(
     [java]     at org.apache.rampart.samples.sample04.Client.main(Unknown Source)
     [java] Caused by: java.lang.NoClassDefFoundError: javax/jms/BytesMessage
     [java]     at java.lang.Class.getDeclaredConstructors0(Native Method)
     [java]     at java.lang.Class.privateGetDeclaredConstructors(
     [java]     at java.lang.Class.getConstructor0(
     [java]     at java.lang.Class.newInstance0(
     [java]     at java.lang.Class.newInstance(
     [java]     at org.apache.axis2.deployment.AxisConfigBuilder.processTransportSenders(
     [java]     ... 6 more
     [java] Java Result: 1

looks like theree's been some changes to the deployment file format though I haven't checked it out. After also doing the last two steps for the serverside for the clientside target I was able to run the client:

     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/client_repositories/sample04/conf
     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/client_repositories/sample04/modules
     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/client_repositories/sample04/modules
     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/temp_client
     [copy] Copying 1 file to <RAMPART_DIR>/samples/basic/build/temp_client
     [java] <ns:echoResponse xmlns:ns=""<>ns:return>Hello world</ns:return></ns:echoResponse>

Nice, but hard to tell whether WS-Security actually was used so let's have a look at the messages that was exchanged.

The messages


The request had the following HTTP headers:

POST /axis2/services/sample04 HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: "urn:echo"
User-Agent: Axis2
Host: localhost:9999
Transfer-Encoding: chunked

and the SOAP request, where the SOAP-header carries the WS-Security elements:

    1 <?xml version='1.0' encoding='UTF-8'?>
    2 <soapenv:Envelope xmlns:soapenv="">
    3   <soapenv:Header>
    4     <wsse:Security
    5       xmlns:wsse=""
    6       soapenv:mustUnderstand="1">
    7       <wsse:BinarySecurityToken
    8         xmlns:wsu=""
    9         EncodingType=""
   10         ValueType=""
   11         wsu:Id="CertId-148082">
   12         MIICTDC....UiaNKiQiu16JCnxc8tGSw3nSPg44aLYmA==
   13       </wsse:BinarySecurityToken>
   14       <ds:Signature
   15         xmlns:ds=""
   16         Id="Signature-21878616">
   17         <ds:SignedInfo>
   18           <ds:CanonicalizationMethod Algorithm="" />
   19           <ds:SignatureMethod Algorithm="" />
   20           <ds:Reference URI="#id-24778599">
   21             <ds:Transforms>
   22               <ds:Transform Algorithm="" />
   23             </ds:Transforms>
   24             <ds:DigestMethod Algorithm="" />
   25             <ds:DigestValue>aIRDYzmMgF/dcP7cUJS6B6T7q8k=</ds:DigestValue>
   26           </ds:Reference>
   27         </ds:SignedInfo>
   28         <ds:SignatureValue>
   29           TVbeyvg....9SH/13k1qpki9...+ZZM+9sIsFs=
   30         </ds:SignatureValue>
   31         <ds:KeyInfo Id="KeyId-6400263">
   32           <wsse:SecurityTokenReference
   33             xmlns:wsu=""
   34             wsu:Id="STRId-3115866">
   35             <wsse:Reference
   36               URI="#CertId-148082"
   37               ValueType="" />
   38           </wsse:SecurityTokenReference>
   39         </ds:KeyInfo>
   40       </ds:Signature>
   41       <wsu:Timestamp
   42         xmlns:wsu=""
   43         wsu:Id="Timestamp-20735553">
   44         <wsu:Created>2008-01-11T19:46:23.656Z</wsu:Created>
   45         <wsu:Expires>2008-01-11T19:51:23.656Z</wsu:Expires>
   46       </wsu:Timestamp>
   47     </wsse:Security>
   48   </soapenv:Header>
   49   <soapenv:Body
   50     xmlns:wsu=""
   51     wsu:Id="id-24778599">
   52     <ns1:echo xmlns:ns1="">
   53       <param0>Hello world</param0>
   54     </ns1:echo>
   55   </soapenv:Body>
   56 </soapenv:Envelope>


The response had these HTTP headers:

HTTP/1.1 200 OK
Date: Fri, 11 Jan 2008 19:46:24 GMT
Server: Simple-Server/1.1
Transfer-Encoding: chunked
Content-Type: text/xml; charset=UTF-8

and the SOAP response which is symmetrical to the request:

    1 <?xml version='1.0' encoding='UTF-8'?>
    2 <soapenv:Envelope xmlns:soapenv="">
    3   <soapenv:Header>
    4     <wsse:Security
    5       xmlns:wsse=""
    6       soapenv:mustUnderstand="1">
    7       <wsse:BinarySecurityToken
    8         xmlns:wsu=""
    9         EncodingType=""
   10         ValueType=""
   11         wsu:Id="CertId-2150700">
   12         MIICTjCCAbcCBEbJZQEw....AqNbjO7+Jbm6+3pyYagQoBpdHZLnR....A3+5xl4VI.......bGxa4+vIbbV4CaUG5s5x
   13       </wsse:BinarySecurityToken>
   14       <ds:Signature
   15         xmlns:ds=""
   16         Id="Signature-6302571">
   17         <ds:SignedInfo>
   18           <ds:CanonicalizationMethod Algorithm="" />
   19           <ds:SignatureMethod Algorithm="" />
   20           <ds:Reference URI="#id-26343425">
   21             <ds:Transforms>
   22               <ds:Transform Algorithm="" />
   23             </ds:Transforms>
   24             <ds:DigestMethod Algorithm="" />
   25             <ds:DigestValue>f0hkA2SGmWtioGBaLwlfsGbSgMk=</ds:DigestValue>
   26           </ds:Reference>
   27           <ds:Reference URI="#SigConf-18206828">
   28             <ds:Transforms>
   29               <ds:Transform Algorithm="" />
   30             </ds:Transforms>
   31             <ds:DigestMethod Algorithm="" />
   32             <ds:DigestValue>W1coTKqCERwIlbeiGL83w7pAEi4=</ds:DigestValue>
   33           </ds:Reference>
   34         </ds:SignedInfo>
   35         <ds:SignatureValue>
   36           IgzqToPMv...ZNrYDe/29JFnAkl....BAYOZMtCPs2XG0btNpX2BegULxk=
   37         </ds:SignatureValue>
   38         <ds:KeyInfo Id="KeyId-7435043">
   39           <wsse:SecurityTokenReference
   40             xmlns:wsu=""
   41             wsu:Id="STRId-4070344">
   42             <wsse:Reference
   43               URI="#CertId-2150700"
   44               ValueType="" />
   45           </wsse:SecurityTokenReference>
   46         </ds:KeyInfo>
   47       </ds:Signature>
   48       <wsu:Timestamp
   49         xmlns:wsu=""
   50         wsu:Id="Timestamp-18092261">
   51         <wsu:Created>2008-01-11T19:46:24.558Z</wsu:Created>
   52         <wsu:Expires>2008-01-11T19:51:24.558Z</wsu:Expires>
   53       </wsu:Timestamp>
   54       <wsse11:SignatureConfirmation
   55         xmlns:wsse11=""
   56         xmlns:wsu=""
   57         Value="TVbeyvgLy...1QgDj8Nau0Fp+ZZM+9sIsFs="
   58         wsu:Id="SigConf-18206828" />
   59     </wsse:Security>
   60   </soapenv:Header>
   61   <soapenv:Body
   62     xmlns:wsu=""
   63     wsu:Id="id-26343425">
   64     <ns:echoResponse xmlns:ns="">
   65       <ns:return>Hello world</ns:return>
   66     </ns:echoResponse>
   67   </soapenv:Body>
   68 </soapenv:Envelope>

Looking at the configuration for the serverside:

   32   <parameter name="InflowSecurity">
   33     <action>
   34       <items>Timestamp Signature</items>
   35       <signaturePropFile></signaturePropFile>
   36     </action>
   37   </parameter>
   39   <parameter name="OutflowSecurity">
   40     <action>
   41       <items>Timestamp Signature</items>
   42       <user>service</user>
   43       <passwordCallbackClass>org.apache.rampart.samples.sample04.PWCBHandler</passwordCallbackClass>
   44       <signaturePropFile></signaturePropFile>
   45       <signatureKeyIdentifier>DirectReference</signatureKeyIdentifier>
   46     </action>
   47   </parameter>

I can be seen that in verifying the request there's a demand for the Timestamp and the certificate used for the signature to be accepted based on the properties in In this specific request the public part is embedded in the BinarySecurityToken and only the path or the specific certificate is to be checked. In the response the DirectReference makes the public part of the X509 certificate embedded with BinarySecurityToken and the password callback is needed to access the private key for creating the signature.


aaron said...

hey brian,

thanks for that. i was curious about one of the steps that you did. "looks like theree's been some changes to the deployment file format though I haven't checked it out. After also doing the last two steps for the serverside for the clientside target I was able to run the client:"

what did you do there specifically?

thanks, aaro

Sweetxml said...

Hey Aaron

The first thing with the deployment descriptor, was that I could not get it to run with the Axis2 snapshot and a quick judgment on the error made me think that somehow a part of the configuration files were the reason (since they were written for veion 1.3) but it not sure at all, just that i works with Axis2-1.3.

The two changes that I did for both the client and server-side was to make the copy of rampart.ram work and the inclusion of the wss4j jar-files in the classpath.

Brgds Brian

Sweetxml said...


To be a bit more precise the error message /exception started with org.apache.axis2.deployment.DeploymentException: javax/jms/BytesMessage. It doesn't use JMS directly so maybe is a dependency issue.

Brgds Brian

Sagar said...

hi Brian,

this post is of great help for newbies like me.Thanks a lot for sharing all the information. It would be great if you could share the "" you used and the sample client and server code (if possible).

Thanks once again.

Sweetxml said...

Hi Sagar

Thank you. Please notice that I didn't create this example it's the dear folks behind WSS4J/Axis2. This and other samples come with the Rampart module that's allready available for download at the Axis2 modules page.

Best regards

Sudhee said...

Thanks Brian.

Sagar said...

hello Brian,

I used the sample code provided by Axis for Rampart. I used "Sign and encrypt messages" method. Now when i am trying to make a call to my service from Client...I am getting the following Exception - "org.apache.axis2.AxisFault: Must Understand check failed for header : Security".

I did Google...but didn't get the solution. Is there anything you can think which is causing the issue.

I have Axis2 deployed in JBOSS. I am using certificates provided in the sample from Axis.


Sweetxml said...

Hi Sagar

Judging from that error message it sounds like the rampart module hasn't been enabled on the serverside.

Qre you trying to run the rampart samples or applying it to your own service?

Brgds Brian

Sagar said...

hello Brian,

I am using my own service not the sample provided by axis.i have modified my "services.xml" as requested by rampart(added InflowSecurity and OutflowSecurity sections).

After adding the below line in my client started working - options.setProperty(Constants.ATTR_MUST_UNDERSTAND,

Now i am getting some other error at the server end - org.apache.axis2.AxisFault: namespace mismatch require found
When i looked at the out going message from client... "" namespace is missing. Do I need to set it some where in my client???

Sweetxml said...

Hi Sagar

First off I don't think it's the right thing to override the mustUnderstand with:


It's hard to when I can't see the messages exchanged. How did you generate the client - from WSDL (WSDL2Java/WSDL2Code) or have you build the client yourself? Have you had the service running without WS-Sec. forehand with success?

Maybe you should try the Axis2 or WSS4J mailing lists.

Brgds Brian

Sagar said...

hello Brian,

you are right. Rampart was not enabled for my service (i had goofed up the services.xml file).I removed the following line also :
Now that part is working fine.

But i am getting a run time exception (CryptoFactory: Cannot load properties: I made sure that the property file is in class path but issue seems to be some thing else. Trying all possible options now.


Sagar said...

hello Brian,

I got it working. Now i am not getting CryptoFactory: Cannot load properties: exception.

I think i have some progress after that. But now i am stuck at some other position.

I am getting General security error (Unexpected number of X509Data: for Signature). I have 2 entries in my .jks file.
Here is my client.prop file :

My jks entries look like this :
Keystore type: jks
Keystore provider: SUN

Your keystore contains 2 entries

service, Aug 20, 2007, trustedCertEntry,
Certificate fingerprint (MD5): 0A:0D:20:99:3E:D3:65:A8:50:CC:20:A6:CB:6F:33:06
client, Aug 20, 2007, keyEntry,
Certificate fingerprint (MD5): 0C:EA:53:98:A5:15:B0:C8:5A:CD:4E:1C:87:A4:71:31

i m not sure why i am getting this exception. You have any clue?


Sagar said...

Correct entries in my client.prop.

Still failing :(

Sweetxml said...

Hi Sagar

It's good to see that you're getting som progress though slow. I do remember fiddeling with all the files, keystores, properties, parameters etc. Often I found the solution much to obvious afterwards.

My best guess is the post to the WSS4J mailing list that is on the same subject Re: [WSS5J 1.5] Unexpected number of X509Data: for Signature maybe it's the same problem you're having.

Brgds Brian

Sagar said...

hello Brian,

Finally everything working :)

Thanks a lot.


Sweetxml said...

Hi Sagar

Congrats, that's excellent news. Hopefully you'll have it much easier with applying Rampart from here. You shouldn't thank me, thank the brave folks that develop and maintain Axis2 and it's modules.

Best regards

Rajakumar said...

Hello guys ,

please help me with this issue

org.apache.axis2.AxisFault: Must Understand check failed for header : Security

thanks Raj

Sweetxml said...

Hi Rajakumar

Maybe, but could you please give a little context like clientside/serverside, platforms versions of axis/rampart etc.

Brgds Brian

Ryan said...

Hi Brian,

Thank you for this, it really helps me alot.

By the way, I didn't use axis2-1.3 but I am using axis2-1.4.1 deployed in tomcat. I followed everything, the service is ok but the client is not, same error as your axis2 nightly. Do you think its because of the version also? Hope you could help me. Thank you in advance.

Thank you for your time.

Best Regards,

Sweetxml said...

Hi Ryan

I haven't looked into it but I guess theres a high probability that the versioning mismatch is the reason, like I experienced in January. I would suggest that you try out either the older axis-1.3 or the nightly rampart/wss4j.

Brgds Brian

rampart user said...

Hi Brian,

Thank you for the nice blog. Any idea why i might be getting this error while running ant client.01 from Rampart samples?
[java] Exception in thread "main" org.apache.axis2.AxisFault: First Element must contain the local name, Envelope , but found h1
[java] at org.apache.axis2.AxisFault.
[java] at org.apache.axis2.transport.
[java] at org.apache.axis2.description.
I am using Axis 2, Rampart 1.4 bin distr.


Sweetxml said...


Me guess is that you're not hitting the right endpoint. It's not related to security, but basically Axis. The message:

First Element must contain the local name, Envelope , but found h1

So it's expecting <soap:Envelope.. but gut <h1.. from the (X)HTML vocab.

Best reagrds

Anonymous said...

Thanks Brian for the prompt reply :)
That was exactly the problem..

While deploying a sample rampart example which refers to axis2.xml in my workspace's conf, i get this error while running client:
[java] org.apache.axis2.phaseresolver.PhaseException: Did not find the desired phase 'Security' while deploying handler 'PolicyBasedSecurityInHandler'.

I tried including the phase order as seen in the AXIS_HOME/conf/axis2.xml...but i still see the same error.

The sample works fine when i replace rahas-1.4.mar and rampart-1.4.mar in my workspace (modules dir) with rampart-1.1.mar and addressing-1.1.mar

Is there any specific setting i need to do when i use 1.4?

Thanks in advance.

Sweetxml said...


First I was surprised that there was such thing as an rampart-1.4 since the Apache Axis2 Modules page still refences version 1.3 as the latest/current and that is compatible with the earlier Axis2-1.3 release. I then checked the subsite for Rampart and discovered not just a facelift but also a 1.4 release.

I've just tried to run some of the samples and with an update to the build.xml to addressing-1.41.mar instead of addressing-1.4.mar:

<property name="addressing.mar" value="addressing-1.41.mar"/>

it seems as if the basic ones run whereas I only got policy sample 01 and 02 to run without errors.

I know this isn't an answer to your question, but you should run with the latest jars and I since I could get the simplest policy samples to run you should be able to find inspiration in these config-files. There might be some bugs, but I didn't bump into the one that you mention in my fast run through and the errors I saw was probably related to the samples and their mockup not being nursed and not the release itself.

Best regards

Sample said...

Your site contains best solution for these messages, i browsed 10-20 sites yet.
Sample messages

Sweetxml said...

Hi Sample

Great that it was of use to you.

Best regards Brian

Sam said...

HI Brian,

Thanks for the article.
I do have a question related to addition of binarysecuritytoken. I do not see any logic in any of the files under Sample4 to generate and add binarysecurity token to the Soap Header. How does it get added?

I am doing a similary implementation and have logic to generate the binarysecuritytoken but I am unable to figure how to add it to the Soap Header using Rampart/Axis2.

Ruby Claire said...
This comment has been removed by the author.