Monday, September 1, 2008

How to pass Security Credentials from BPEL to ESB to a Web Service

I have seen people facing problems to pass security credentials from an ESB routing service to a WS-Security compliant Web Service. Passing security credentials from ESB routing service is possible but it's tricky. You need to play with the XSLT transformation to add WS-Security tokens in SOAP header of a Web Service request.

Oracle ESB is having four extension function for SOAP header manipulation:

1. String getRequestHeader(String xpathExpression,String namespaceDecl)
2. void setOutboundHeader(String xpathExpression,String value, String namespaceDecl)
3. String getInboundResponseHeader(String xpathExpression,String namespaceDecl)
4. void setResponseHeader(String xpathExpression,String value, String namespaceDecl)

here,
xpathExpression - XPath expression to get/set
value - value to be set for the xpathExpression
namespaceDecl - namespace declarations in the form ‘prefix=namespace;’

You need to add the four expressions given below in the XSLT map before invoking a WS-Security compliant Web Service. First two expressions extract user name and password from the incoming SOAP header and the last two expressions add security credentials in the outbound SOAP header.

<xsl:variable name="userName"
select="ehdr:getRequestHeader('/soap:Header/wsse:Security/wsse:UsernameToken/wsse:Username','wsse=http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd; soap=http://schemas.xmlsoap.org/soap/envelope/;')"/>

<xsl:variable name="password"
select="ehdr:getRequestHeader('/soap:Header/wsse:Security/wsse:UsernameToken/wsse:Password','wsse=http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd; soap=http://schemas.xmlsoap.org/soap/envelope/;')"/>

<xsl:variable name="setUsername"
select="ehdr:setOutboundHeader('/soap:Header/wsse:Security/wsse:UsernameToken/wsse:Username',$userName,'wsse=http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd;')"/>

<xsl:variable name="setPassword"
select="ehdr:setOutboundHeader('/soap:Header/wsse:Security/wsse:UsernameToken/wsse:Password',$password,'wsse=http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd;')"/>

See my previous posts How to set security credentials dynamically in Oracle BPEL and Invoking WS-Security compliant Web Services from Oracle BPEL to learn how to send security credentials from a BPEL process. You can download sample BPEL and ESB projects from here. You can use these projects for your reference.

How to set security credentials dynamically in Oracle BPEL

Few months ago I have written a post on invoking WS-Security compliant services, In Oracle BPEL you can either propagate the security credentials coming from the caller process or you can hard-code the tokens in partner link properties.

If you want to invoke a WS-Security compliant web service and want to pass user supplied security tokens, Oracle BPEL does not let you set the security credential dynamically. You need to manually create a UserNameToken and then you need to pass the token as a SOAP header.

Follow the steps given below to change and pass security credentials dynamically:

  • Create 3 variable as given below:

<variable name="securityContext" element="ns2:Security"/>

<variable name="userNameToken" element="ns2:UsernameToken"/>

<variable name="pswd" element="ns2:Password"/>

  • Assign incoming security credentials to these variables:

<assign name="AssignSecurityCredentials">

<copy>

<from variable="inputVariable" part="payload"

query="/client:SampleRequest/client:pswd"/>

<to variable="pswd" query="/wsse:Password"/>

</copy>

<copy>

<from variable="inputVariable" part="payload"

query="/client:SampleRequest/client:user"/>

<to variable="userNameToken"

query="/wsse:UsernameToken/wsse:Username"/>

</copy>

<bpelx:insertAfter>

<bpelx:from variable="pswd" query="/wsse:Password"/>

<bpelx:to variable="userNameToken"

query="/wsse:UsernameToken/wsse:Username"/>

</bpelx:insertAfter>

<bpelx:append>

<bpelx:from variable="userNameToken" query="/wsse:UsernameToken"/>

<bpelx:to variable="securityContext" query="/wsse:Security"/>

</bpelx:append>

</assign>

  • Pass the security credentials to the calling service like the expression given below:

<invoke name="InvokeAxisService" partnerLink="PartnerLinkAxisService"

portType="ns1:sample03PortType" operation="echo"

inputVariable="Invoke_1_echo_InputVariable"

outputVariable="Invoke_1_echo_OutputVariable"

bpelx:inputHeaderVariable="securityContext"/>

  • Complete you BPEL process by adding required functionalities then deploy and test it.