Wednesday 11 February 2015

JMeter - Generating WSS UsernameToken with PasswordDigest, Noonce and Timestamp

Recently, I was tasked to do some performance testing for a web service that was using WSS UsernameToken for authentication. So illustration purposes, it looked like so:


<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">

<SOAP-ENV:Header>

<wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">

<wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-76C2EC437437B987531423677905104107">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">c/QVFZ+qsKvL3bDJzPkp/pmYpjY=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">4o1vEGk5DLAWyV9TufAKDQ==</wsse:Nonce>
<wsu:Created>2015-02-11T18:05:05.104Z</wsu:Created>
</wsse:UsernameToken>


</wsse:Security>

</SOAP-ENV:Header>
  <SOAP-ENV:Body>
.....
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>




At first, you would think that JMeter would already have generation of the header present - but unfortunately, that is not the case. You have to use a BeanShell PreProcessor to generate this header. The solution presented here uses two additional jars, that have to be added to the lib folder in JMeter:

  1. wss4j-1.6.12.jar
  2. xmlsec-1.5.7.jar
Now you must add a BeanShell Preprocessor to your HTTP Request. Ensure that you have the ${noonce} placeholder within the security tag of the soap header. Our preprocessor will fill this with the username token.


Finally, attach the following script to the BeanShell Preprocessor: