How to add WS-Security Username Token for a SOAP request using Apigee Edge

Hi All,

Can anyone help me on adding ws-security username token to soap request before doing any further operation.

Thanks..!

Solved Solved
1 4 8,368
1 ACCEPTED SOLUTION

Sure.

I understand that there is a SOAP request sent in, and you would like to configure an Apigee API Proxy to augment the inbound SOAP message with a Ws-Security username token.

This is pretty easy to do with a JavaScript callout and an XSL. The JS callout is used to compute the Password digest. In WS-Sec, the Password digest is defined as:

digest = base64 ( sha1 ( nonce + created + password ) )  

...where the nonce is any string, the created is a timestamp formatted like 2017-12-18T21:55:00Z , and the password is the password.

In Apigee Edge, we can use the variable "messageid" as the nonce. The created timestamp is easy to create in JavaScript. And the sha1 and base64 encoding are also easy. The JS code looks like this:

var password = resolveVariableReference(properties.password);
var nonce = context.getVariable('messageid');
var created = getCreated();
var sha1 = crypto.getSHA1();
sha1.update(nonce + created + password);
var hashed_token = sha1.digest64();

context.setVariable('encoded_password', hashed_token);
context.setVariable('nonce', nonce);
context.setVariable('created', created);

Once those 3 things are computed, we can then inject the right header using XSL.

The result is like this:

$ curl -X POST https://amer-demo2-test.apigee.net/add-ws-sec-header/t1 -H content-type:text/xml -d '
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <GetProxy xmlns="">
      <ProxiesList/>
    </GetProxy>
  </Body>
</Envelope>
'
<soap:Envelope 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"
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xslt="http://xml.apache.org/xslt">
   <soap:Header>
      <wsse:Security>
         <wsse:UsernameToken>
            <wsse:Username>user1234567</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">1tjDFz3NzJsTUZsBXtgmb0O4ic8=</wsse:Password>
            <wsse:Nonce>rrt-00b5fb16e15afb3d1-c-ea-13443-14273294-1</wsse:Nonce>
            <wsu:Created xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2017-12-18T21:55:00Z</wsu:Created>
         </wsse:UsernameToken>
      </wsse:Security>
   </soap:Header>
   <soap:Body>
      <GetProxy>
         <ProxiesList/>
      </GetProxy>
   </soap:Body>
</soap:Envelope>
 

See attached for a working API proxy.

apiproxy-add-ws-sec-username-token.zip

View solution in original post

4 REPLIES 4

Sure.

I understand that there is a SOAP request sent in, and you would like to configure an Apigee API Proxy to augment the inbound SOAP message with a Ws-Security username token.

This is pretty easy to do with a JavaScript callout and an XSL. The JS callout is used to compute the Password digest. In WS-Sec, the Password digest is defined as:

digest = base64 ( sha1 ( nonce + created + password ) )  

...where the nonce is any string, the created is a timestamp formatted like 2017-12-18T21:55:00Z , and the password is the password.

In Apigee Edge, we can use the variable "messageid" as the nonce. The created timestamp is easy to create in JavaScript. And the sha1 and base64 encoding are also easy. The JS code looks like this:

var password = resolveVariableReference(properties.password);
var nonce = context.getVariable('messageid');
var created = getCreated();
var sha1 = crypto.getSHA1();
sha1.update(nonce + created + password);
var hashed_token = sha1.digest64();

context.setVariable('encoded_password', hashed_token);
context.setVariable('nonce', nonce);
context.setVariable('created', created);

Once those 3 things are computed, we can then inject the right header using XSL.

The result is like this:

$ curl -X POST https://amer-demo2-test.apigee.net/add-ws-sec-header/t1 -H content-type:text/xml -d '
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <GetProxy xmlns="">
      <ProxiesList/>
    </GetProxy>
  </Body>
</Envelope>
'
<soap:Envelope 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"
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:xslt="http://xml.apache.org/xslt">
   <soap:Header>
      <wsse:Security>
         <wsse:UsernameToken>
            <wsse:Username>user1234567</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">1tjDFz3NzJsTUZsBXtgmb0O4ic8=</wsse:Password>
            <wsse:Nonce>rrt-00b5fb16e15afb3d1-c-ea-13443-14273294-1</wsse:Nonce>
            <wsu:Created xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2017-12-18T21:55:00Z</wsu:Created>
         </wsse:UsernameToken>
      </wsse:Security>
   </soap:Header>
   <soap:Body>
      <GetProxy>
         <ProxiesList/>
      </GetProxy>
   </soap:Body>
</soap:Envelope>
 

See attached for a working API proxy.

apiproxy-add-ws-sec-username-token.zip

Thank you..! @Dino .. Answer works well..!

Hi Dino,

I have the same requirement.  Currently we are using Broadcomm layer7 I have done adding WS-S Username Token and ws-security. Now we are planning to move all proxies from Layer7 to Apigee. 

on Layer7, once SOAP Payload reaches proxy, we are adding plain username/password attached here for your reference and then adding ws-security to the request payload and sending it to backend. here is the screenshot from layer7. I am trying to download zip file which was in accepted solution but getting 403 error.

on Layer7, it is simple and we just need to drop Assertions. Can you please help me on how can we achieve same requirement in APIGEE.

 

rajkalgur_0-1702166008704.png

rajkalgur_2-1702167505138.png

 

 

 

Hi Raj

I saw that you also asked a new question. I answered over there. https://www.googlecloudcommunity.com/gc/Apigee/Applying-WS-S-UsernameToken-and-WS-Security/m-p/67996...