tisdag 18 juni 2013

Integrating Mule ESB Community Edition with IBM WebSphere DataPower SOA or other SOAP services where Signing of Binary Security token is nessesary

Integrating Mule ESB with IBM WebSphere DataPower WS-Security based SOAP services may become very frustrating. Especially if you are trying to do it without WS-Security policies.

The real hurdle to get pass is that some of these product's SOAP endpoints, requires the Binary security token itself to be X509 signed and referenced within the  <ds:SignedInfo> 
along with the message body as part of the SOAP message - not easily accomplished within Mule.

As stated above this can be accomplished using WS-Security profiles and have the <sp:ProtectTokens/> enabled withing your profile.
The profile can be a part of your service WSDL or added on a local copy that you edit yourself, just for the client but in my example I will demonstrate how to do it when you do not have the possibility to use profiles, WSDL's etc.

Enabling WS-Security is by Mulesoft in fact marked as an Enterprise only feature of Mule ESB, however my example demonstrates how to do this with Community Edition.

By the time of this writing ( Mule ESB 3.4 ) it is not even possible to do it by chaining two
org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor
after each other first signing the body and getting the Binary security token and then in a second sign the Binary security token itself.
I could not even get that done in Apache CXF through Spring beans configuration in Mule.

I have tried lot's of other ways to get it done as well, but let's instead demonstrate a way ahead that actually works.

Pass the SOAP!


First lets create a Web service that represents the server so that we have something standalone to test against.  I have used Mule studios template as a starting point to setup this example.



 <?xml version="1.0" encoding="UTF-8"?>  
 <mule xmlns:http="http://www.mulesoft.org/schema/mule/http"  
      xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"  
      xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="  
 http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd   
 http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd  
 http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd">  
   <flow name="X509SignedAndEncryptedServiceFlow" doc:name="X509SignedAndEncryptedServiceFlow">  
     <http:inbound-endpoint address="http://localhost:63081/services/x509" exchange-pattern="request-response" doc:name="HTTP Inbound Endpoint"/>  
     <cxf:jaxws-service serviceClass="com.mulesoft.mule.example.security.Greeter" doc:name="Secure UsernameToken Signed service">  
       <cxf:ws-security>  
         <cxf:ws-config>  
           <cxf:property key="action" value="UsernameToken Signature Timestamp"/>  
           <!-- <cxf:property key="action" value="UsernameToken Signature Timestamp Encrypt"/> -->  
           <cxf:property key="signaturePropFile" value="wssecurity_server.properties"/>  
           <!-- <cxf:property key="decryptionPropFile" value="wssecurity_server.properties"/> -->  
           <cxf:property key="passwordCallbackClass" value="com.mulesoft.mule.example.security.PasswordCallback"/>  
         </cxf:ws-config>  
       </cxf:ws-security>  
     </cxf:jaxws-service>  
     <component class="com.mulesoft.mule.example.security.GreeterService" doc:name="Greeter Service"/>  
   </flow>  
 </mule>  

Create a Greeter service that simply says Hello.

 package com.mulesoft.mule.example.security;  
 /*  
  * $Id: GreeterService.java 18408 2010-12-09 19:44:58Z travis.carlson $  
  * --------------------------------------------------------------------------------------  
  *  
  * (c) 2003-2010 MuleSoft, Inc. This software is protected under international copyright  
  * law. All use of this software is subject to MuleSoft's Master Subscription Agreement  
  * (or other master license agreement) separately entered into in writing between you and  
  * MuleSoft. If such an agreement is not in place, you may not use the software.  
  */  
 public class GreeterService implements Greeter  
 {  
   public String greet(String name)  
   {  
     return "Hello " + name;  
   }  
 }  

Expose it as a Webservice.

 /*  
  * $Id: Greeter.java 18408 2010-12-09 19:44:58Z travis.carlson $  
  * --------------------------------------------------------------------------------------  
  *  
  * (c) 2003-2010 MuleSoft, Inc. This software is protected under international copyright  
  * law. All use of this software is subject to MuleSoft's Master Subscription Agreement  
  * (or other master license agreement) separately entered into in writing between you and  
  * MuleSoft. If such an agreement is not in place, you may not use the software.  
  */  
 package com.mulesoft.mule.example.security;  
 import javax.jws.WebParam;  
 import javax.jws.WebResult;  
 import javax.jws.WebService;  
 @WebService  
 public interface Greeter  
 {  
   @WebResult(name="name")  
   public String greet(@WebParam(name="name") String name);  
 }  

We also need a Password callback handler for our service.

 package com.mulesoft.mule.example.security;  
 /*  
  * $Id: PasswordCallback.java 18408 2010-12-09 19:44:58Z travis.carlson $  
  * --------------------------------------------------------------------------------------  
  *  
  * (c) 2003-2010 MuleSoft, Inc. This software is protected under international copyright  
  * law. All use of this software is subject to MuleSoft's Master Subscription Agreement  
  * (or other master license agreement) separately entered into in writing between you and  
  * MuleSoft. If such an agreement is not in place, you may not use the software.  
  */  
 import java.io.IOException;  
 import javax.security.auth.callback.Callback;  
 import javax.security.auth.callback.CallbackHandler;  
 import javax.security.auth.callback.UnsupportedCallbackException;  
 import org.apache.ws.security.WSPasswordCallback;  
 public class PasswordCallback implements CallbackHandler  
 {  
   public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException  
   {  
     WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];  
     if (pc.getIdentifier().equals("myclientkey"))  
     {  
       pc.setPassword("ckpass");  
     }  
     else if (pc.getIdentifier().equals("myservicekey"))  
     {  
       pc.setPassword("skpass");  
     }  
   }  
 }  

We will create a self signed X509 certificate and private / public keypair to test with.

First using java's keytool setup the keystores and keys:

 keytool -genkey -keyalg RSA -sigalg SHA1withRSA -validity 730 -alias myservicekey -keypass skpass -storepass sspass -keystore serviceKeystore.jks -dname "cn=localhost"  
 keytool -genkey -keyalg RSA -sigalg SHA1withRSA -validity 730 -alias myclientkey -keypass ckpass -storepass cspass -keystore clientKeystore.jks -dname "cn=clientuser"  

Note that these keys are self-signed and should never be used in production.

Setup two-way trust between the SOAP client and the web service. That means load each of the public keys into the keystore of the other.

 keytool -export -rfc -keystore clientKeystore.jks -storepass cspass -alias myclientkey -file MyClient.cer  
 keytool -import -trustcacerts -keystore serviceKeystore.jks -storepass sspass -alias myclientkey -file MyClient.cer -noprompt  
 keytool -export -rfc -keystore serviceKeystore.jks -storepass sspass -alias myservicekey -file MyService.cer  
 keytool -import -trustcacerts -keystore clientKeystore.jks -storepass cspass -alias myservicekey -file MyService.cer -noprompt  

It is now safe to delete the temporary .cer files.

Now lets setup two WS-Security configuration files in your resources folder one for the client called wssecurity_client.properties:

 org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin  
 org.apache.ws.security.crypto.merlin.keystore.type=jks  
 org.apache.ws.security.crypto.merlin.keystore.password=cspass  
 org.apache.ws.security.crypto.merlin.keystore.alias=myclientkey  
 org.apache.ws.security.crypto.merlin.file=clientKeystore.j  

and one for the server called wssecurity_server.properties

 org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin  
 org.apache.ws.security.crypto.merlin.keystore.type=jks  
 org.apache.ws.security.crypto.merlin.keystore.password=sspass  
 org.apache.ws.security.crypto.merlin.file=serviceKeystore.jks  
 org.apache.ws.security.crypto.m  

Now create a separate .mflow file for our client.



 <?xml version="1.0" encoding="UTF-8"?>  
 <mule xmlns:http="http://www.mulesoft.org/schema/mule/http"  
      xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"  
      xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd  
 http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd  
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd  
 http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd">  
 <flow name="SecurityClients" doc:name="SecurityClients">  
     <http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="63080" path="client" doc:name="HTTP Inbound Endpoint"/>  
     <set-payload value="#[message.inboundProperties['http.query.params']['name']]" doc:name="Set payload with 'name' query param"/>  
     <set-variable variableName="clientType" value="#[message.inboundProperties['http.query.params']['clientType']]" doc:name="Set clientType"/>  
     <choice doc:name="Choice">  
       <when expression="#[clientType == 'x']">  
           <flow-ref name="X509Flow" doc:name="Invoke x509 Encrypted sub-flow"/>  
       </when>  
       <otherwise>  
           <set-payload value="Client type is not supported" doc:name="Client type is not supported"/>  
       </otherwise>  
     </choice>  
     <set-property propertyName="Content-Type" value="text/plain" doc:name="Set response Content-Type"/>  
     <catch-exception-strategy doc:name="Catch Exception Strategy">  
          <set-payload value="There has been an Error processing the request" doc:name="Set Payload"/>  
          <set-property propertyName="Content-Type" value="text/plain" doc:name="Set response Content-Type"/>  
     </catch-exception-strategy>  
   </flow>  
   <sub-flow name="unsecure" doc:name="unsecure">  
     <cxf:jaxws-client operation="greet" serviceClass="com.mulesoft.mule.example.security.Greeter" doc:name="Unsecure SOAP client" doc:description="Unsecure SOAP client"/>  
     <http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="63081" path="services/unsecure" doc:name="Invoke unsecure Web Service"/>  
   </sub-flow>  
   <sub-flow name="X509Flow" doc:name="X509Flow">  
 --------------------------------  
The exiting stuff
 --------------------------------  
     <http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="63081" path="services/x509" doc:name="Invoke usernameToken Encrypted Web Service"/>  
   </sub-flow>  
 </mule>  




The exiting stuff. Well that is in this case the stuff related to our jaxws client that is about to call our Greeter service.



We make use of cxf:outInterceptor defining three interceptors in a chain like this.

     <cxf:jaxws-client operation="greet" serviceClass="com.mulesoft.mule.example.security.Greeter" doc:name="X509 client">  
             <cxf:outInterceptors>  
             <spring:bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">  
                <spring:constructor-arg>  
                     <spring:map>  
                        <spring:entry key="action" value="UsernameToken"/>  
                        <spring:entry key="user" value="myclientkey"/>   
                        <spring:entry key="passwordCallbackClass" value="com.mulesoft.mule.example.security.PasswordCallback"/>  
                     </spring:map>  
                 </spring:constructor-arg>  
              </spring:bean>  
              <spring:bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor"/>   
              <spring:bean class="se.redpill.SigningHack">  
              </spring:bean>   
              <spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" id="LoggingOut">  
                  <spring:property name="prettyLogging" value="true" />  
             </spring:bean>  
         </cxf:outInterceptors>    
     </cxf:jaxws-client>  

The first one is simply a WSS4JOutInterceptor  that has the standard Apache CXF action of UsernameToken specified as expected by our Greeter service. The second is a standard SAAJOutInterceptor which we will need to set up the outgoing chain to build a SAAJ tree instead of writing directly to the output stream. The last interceptor is for logging the SOAP that is to be sent to console and the one that is interesting and is doing the magic is se.redpill.SiningHack


 package se.redpill;  
 import java.io.InputStream;  
 import java.security.KeyStore;  
 import java.security.cert.X509Certificate;  
 import java.util.ArrayList;  
 import java.util.List;  
 import javax.xml.soap.MessageFactory;  
 import javax.xml.soap.SOAPEnvelope;  
 import javax.xml.soap.SOAPMessage;  
 import javax.xml.transform.dom.DOMSource;  
 import org.apache.cxf.binding.soap.SoapMessage;  
 import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;  
 import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;  
 import org.apache.cxf.interceptor.Fault;  
 import org.apache.cxf.phase.Phase;  
 import org.apache.ws.security.WSConstants;  
 import org.apache.ws.security.WSEncryptionPart;  
 import org.apache.ws.security.WSSConfig;  
 import org.apache.ws.security.components.crypto.Crypto;  
 import org.apache.ws.security.components.crypto.CryptoType;  
 import org.apache.ws.security.components.crypto.Merlin;  
 import org.apache.ws.security.message.WSSecHeader;  
 import org.apache.ws.security.message.WSSecSignature;  
 import org.apache.ws.security.message.WSSecTimestamp;  
 import org.apache.ws.security.message.token.X509Security;  
 import org.apache.ws.security.util.Loader;  
 import org.apache.ws.security.util.WSSecurityUtil;  
 import org.w3c.dom.Document;  
 /**  
  *   
  * SigningHack.java  
  * Purpose: X509 signs SOAP Body BST.  
  *  
  * @author Jon Åkerström  
  *  
  */  
 public class SigningHack extends AbstractSoapInterceptor  
 {  
      private SAAJOutInterceptor saajOut = new SAAJOutInterceptor();  
      public SigningHack() {  
           super(Phase.PRE_PROTOCOL_ENDING );    
   }  
      public SOAPMessage signSOAPEnvelope(SOAPEnvelope unsignedEnvelope) throws Exception  
       {  
         // Signs a SOAP envelope according to the  
         // WS Specification (X509 profile) and adds the signature data  
         // to the envelope.  
         Crypto crypto = new Merlin();  
         KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());  
         ClassLoader loader = Loader.getClassLoader(SigningHack.class);  
         InputStream input = Merlin.loadInputStream(loader, "clientKeystore.jks");  
         keyStore.load(input, "cspass".toCharArray());  
         ((Merlin)crypto).setKeyStore(keyStore);  
         Document doc = unsignedEnvelope.getOwnerDocument();  
         WSSecHeader secHeader = new WSSecHeader();  
         secHeader.insertSecurityHeader(doc);  
         // Get a certificate, convert it into a BinarySecurityToken and add it to the security header  
         CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);  
         cryptoType.setAlias("myclientkey");  
         X509Certificate[] certs = crypto.getX509Certificates(cryptoType);  
         // Add the signature  
         X509Security bst = new X509Security(doc);  
         String certUri = WSSConfig.getNewInstance().getIdAllocator().createSecureId("X509-", certs[0]);  
         bst.setX509Certificate(certs[0]);  
         bst.setID(certUri);  
         WSSecurityUtil.prependChildElement(secHeader.getSecurityHeader(), bst.getElement());  
         WSSecSignature sign = new WSSecSignature();  
         sign.setUserInfo("myclientkey", "ckpass");  
         sign.setSignatureAlgorithm(WSConstants.RSA_SHA1);  
         sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);  
         sign.setX509Certificate(certs[0]);  
         List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();  
         // Add SOAP Body  
         String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());  
         WSEncryptionPart encP =new WSEncryptionPart(WSConstants.ELEM_BODY, soapNamespace, "Content");  
         parts.add(encP);  
         // Add BST  
         encP = new WSEncryptionPart(WSConstants.BINARY_TOKEN_LN, WSConstants.WSSE_NS, "Element");  
         encP.setElement(bst.getElement());  
         parts.add(encP);  
         sign.setParts(parts);  
         WSSecTimestamp timestamp = new WSSecTimestamp();  
         timestamp.setTimeToLive(600);  
         timestamp.build(doc, secHeader);  
         parts.add(new WSEncryptionPart(timestamp.getId()));  
         sign.setCustomTokenId(bst.getID());  
         sign.setCustomTokenValueType(bst.getValueType());  
         sign.prepare(doc, crypto, secHeader);  
         List<javax.xml.crypto.dsig.Reference> referenceList =   
         sign.addReferencesToSign(parts, secHeader);  
         sign.computeSignature(referenceList, false, null);  
         Document signedDoc = doc;  
         DOMSource src = new DOMSource(signedDoc);  
         MessageFactory mf = MessageFactory.newInstance();  
            SOAPMessage soapMsg = mf.createMessage();  
            soapMsg.getSOAPPart().setContent(src);  
         return soapMsg;  
       }  
      @Override  
   public void handleMessage(SoapMessage message) throws Fault {  
     SOAPMessage sm = message.getContent(SOAPMessage.class);  
     try   
     {  
       sm.writeTo(System.out);  
     } catch (Exception e)   
     {  
          e.printStackTrace();  
     }  
           try   
           {  
                SOAPEnvelope se = sm.getSOAPPart().getEnvelope();  
                message.setContent(SOAPMessage.class, signSOAPEnvelope(se));  
           } catch (Exception e1) {  
                // TODO Auto-generated catch block  
                e1.printStackTrace();  
           }  
      }  
 }  

Note the super(Phase.PRE_PROTOCOL_ENDING );  
specifying in which CXF interceptor Phase that this SoapInterceptor should insert itself into.
It is very important that you choose the correct phase.

Next the handleMessage method receives the SOAP and passes it to the signSOAPEnvelope 
method for processing by WSS4J statements. Note that in this example i only add the body and the Binary security token to the computing signature and its references. You could of course add whatever elements you like , the Timestamp, UsernameToken etc.


You can test the whole thing by open up your browser and call something like:
http://localhost:63080/client?clientType=x&name=John%20Doe

VOILA!

The SOAP produced should look something like this. Especially notice the
"ds:Reference URI="#X509-"
data
within the <ds:SignedInfo> field that is the cause for this whole demonstration.

 <?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  
  <soap:Header>  
   <wsse:Security 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" soap:mustUnderstand="1">  
    <wsu:Timestamp wsu:Id="TS-2">  
     <wsu:Created>2013-06-17T18:14:06.212Z</wsu:Created>  
     <wsu:Expires>2013-06-17T18:24:06.212Z</wsu:Expires>  
    </wsu:Timestamp>  
    <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-62121A83C77862F71F13714928462051">MIIBoTCCAQqgAwIBAgIEUb8P/zANBgkqhkiG9w0BAQUFADAVMRMwEQYDVQQDEwpjbGllbnR1c2VyMB4XDTEzMDYxNzEzMzI0N1oXDTE1MDYxNzEzMzI0N1owFTETMBEGA1UEAxMKY2xpZW50dXNlcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAgHs1KqFTZGbNM/PoqcXk2GWzw9AAsYRhzCf3GOxNUzMgGvKpRZjUYOlwIozcoJ1optb/g/9Ku6NSKhq5EWOBcsTon+C99dbwkgTIugPrbcappAftrqBSU7/fSEyaLhagLt/NVwyyQ++Ax4HU8BFu84TRkpoqyPgjII7hV3FirKMCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBgCqrNwGAlcPUfjx4FcYF/5bBdgbCEkCC2EEJv3Sm8AIAyHDJN0bxQf6qkT8qVlz2g0EWtNBN7KBUUO1PhDXBpuii90XRNtv5C1dF2V+c1uFhIGloSqsWW5/Ia8k3inv0edFPwqp6oXjNjLWWI03msRr5VaNKrASXsWJ7cBIWg5A==</wsse:BinarySecurityToken>  
    <wsse:UsernameToken wsu:Id="UsernameToken-1">  
     <wsse:Username>myclientkey</wsse:Username>  
     <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">eGcv38RgFW+oum+97nHwSkm5UKs=</wsse:Password>  
     <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">S2AMgJhwZjpQiTnNcW1mxw==</wsse:Nonce>  
     <wsu:Created>2013-06-17T18:14:06.128Z</wsu:Created>  
    </wsse:UsernameToken>  
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-4">  
     <ds:SignedInfo>  
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">  
       <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>  
      </ds:CanonicalizationMethod>  
      <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>  
      <ds:Reference URI="#id-3">  
       <ds:Transforms>  
        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">  
         <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList=""/>  
        </ds:Transform>  
       </ds:Transforms>  
       <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>  
       <ds:DigestValue>AWj0MyBAJSSQtq9VQKWsHLleyM0=</ds:DigestValue>  
      </ds:Reference>  
      <ds:Reference URI="#X509-62121A83C77862F71F13714928462051">  
       <ds:Transforms>  
        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">  
         <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>  
        </ds:Transform>  
       </ds:Transforms>  
       <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>  
       <ds:DigestValue>VQtibH91UIJiSb6dU0UEUsOu9gU=</ds:DigestValue>  
      </ds:Reference>  
      <ds:Reference URI="#TS-2">  
       <ds:Transforms>  
        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">  
         <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsse soap"/>  
        </ds:Transform>  
       </ds:Transforms>  
       <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>  
       <ds:DigestValue>aCvHMOWvJRmA99t0o2SrDznkZmI=</ds:DigestValue>  
      </ds:Reference>  
     </ds:SignedInfo>  
     <ds:SignatureValue>P88VKXSErnMoMAMp+xaPDvlPkr+kb6U7Xh8GW0Ctz7HJlH94A3YCrDo9wq1b20jz2Ckr4neSxDQJ  
 QE4unfhu6UG8jnPIbROSv/Eu9NX2MWD/Qtevf+j+AHsRGyaDE6WpHxcAeOnSDPs2KUOiRzLLWaOP  
 ClDsIcLVe/ca2mahXKM=</ds:SignatureValue>  
     <ds:KeyInfo Id="KI-62121A83C77862F71F13714928462132">  
      <wsse:SecurityTokenReference wsu:Id="STR-62121A83C77862F71F13714928462153">  
       <wsse:Reference URI="#X509-62121A83C77862F71F13714928462051" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>  
      </wsse:SecurityTokenReference>  
     </ds:KeyInfo>  
    </ds:Signature>  
   </wsse:Security>  
  </soap:Header>  
  <soap:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-3">  
   <ns2:greet xmlns:ns2="http://security.example.mule.mulesoft.com/">  
    <name>John</name>  
   </ns2:greet>  
  </soap:Body>  
 </soap:Envelope>  

Note that validation of the signed data on the server side is beyond the scope of this article which is focusing on the client side issue of signing the binary security token.

3 kommentarer:

  1. Also some WebLogic components are known to require signed BST.

    SvaraRadera
  2. That is very interesting; you are a very skilled blogger. A very nice guide. I will definitely follow these tips. Thank you for sharing such detailed article.

    Mulesoft online training

    SvaraRadera

  3. I am really enjoying reading your well written articles. It looks like you spend a lot of effort and time on your blog. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work..

    Mulesoft online training india

    SvaraRadera