Saturday, August 31, 2013

WSO2 ESB - Adding complex SOAP headers to a message

WSO2 ESB comprises of about 40+ mediators, using which you can perform several actions on the the SOAP messages being passed through. One such requirement would be to manipulate SOAP headers of a message.


What if you need to add a complex header structure to the message as follows,

<soapenv:Header>
<urn:AuthenticationInfo>
<urn:userName>userName</urn:userName>
<urn:password>password</urn:password>
</urn:AuthenticationInfo>
</soapenv:Header>
view raw header.xml hosted with ❤ by GitHub


A real use case of this kind of a requirement will be, you have a secured proxy service in ESB with UsernameToken Policy applied, but the backend service is not secured according to WSSE standards, but having its own way of authenticating, hence it requires messages coming to that endpoint having the structure of the headers as above, and username and password header values need to set with the username and password contains in the WSSE usernameToken of the original request.

That can be achieved using a class / custom mediator which involves writing some Java code, but if you need to avoid deploying / maintain a separate package for that you can chose either Header mediator, XSLT mediator or Script mediator.

Here I'm going to show how the script mediator can be used for the above use case.

Since you have enabled WS security in the proxy service, a valid SOAP request needs to contain the WSSE security headers, as follows.
<soapenv:Envelope xmlns:dat="http://ws.wso2.org/dataservice" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header><wsse:Security soapenv: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">
<wsu:Timestamp wsu:Id="TS-48">
<wsu:Created>2013-08-31T00:27:32Z</wsu:Created>
<wsu:Expires>2013-08-31T00:30:52Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken wsu:Id="UsernameToken-47">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">FGwe+CvT7JnwKFBv0C/R7Q==</wsse:Nonce>
<wsu:Created>2013-08-31T00:27:32.237Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<dat:getEmployee/>
</soapenv:Body>
</soapenv:Envelope>
view raw request.xml hosted with ❤ by GitHub


As highlighted in the above request message, you have to extract the username and password values coming in the request and set those in the header structure which is expected by the backend service.

In order to do that your Script Mediator configuration will be as follows,
<script language="js">
var wsse = new Namespace('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd');
var envelope = mc.getEnvelopeXML();
var username = envelope..wsse::Username.toString();
var password = envelope..wsse::Password.toString();
mc.addHeader(false, <urn:AuthenticationInfo><urn:userName>{username}</urn:userName><urn:password>{password}</urn:password></urn:AuthenticationInfo>);
</script>

That's it..! If you do a full log in insequence you will see the message with added complex headers.. In a future post I Will show you how to use Header mediator and XSLT mediator to achieve the same task.

References
[1] http://docs.wso2.org/display/ESB470/Script+Mediator
[2] http://wso2.com/project/mashup/0.2/docs/e4xquickstart.html