How to add wsse security header for SOAP client in JAVA using UsenameToken and PasswordDigest

I am trying to create a SOAP client in Java using AXIS2. The web service I'm trying to use uses a security header with the UserName token and Password Digest token. I can build REQUEST HEADER, REQUEST BODY, and also add a security header.

The following shows a SOAP request that works fine from the SOAP interface:

POST http://<OUR WSDL>HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
Authorization: Basic c2FtczpzYW1z
Content-Length: 2920
Host: hostnameqa-web.cable.com:80
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://xml.comcast.com/sams/tts/consumerservice/v1_2">
   <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">
         <wsse:UsernameToken wsu:Id="UsernameToken-42">
            <wsse:Username>username1</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">pifAlJJNQAo8Tqi+F95kpz+8UvM=</wsse:Password>
            <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">99lpCD9kwSvUd78EA3Humw==</wsse:Nonce>
            <wsu:Created>2015-05-13T15:18:10.100Z</wsu:Created>
         </wsse:UsernameToken>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <v1:create>
         <!--Optional:-->
         <v1:CreateConsTicketRequest>

            <Header>
               <Requester>requestor</Requester>
               <Submitter>
                  <Type>Real</Type> 
                  <Value>Submitter</Value> 
               </Submitter>
               <TimeStamp>
                  <Date>2014-05-30</Date>
                  <Time>22:38:26</Time>
                  <TimeZone>UTC</TimeZone>
               </TimeStamp>
               <TransactionId>1</TransactionId> 
            </Header>

            <Body>
               <CTicket>
                  <ContactInformation>
                     <Name>First Name123, Last Name123</Name>
                     <Phone>1234567893</Phone>
                     <Email>email@testing.com</Email>
                  </ContactInformation>

                  <TimeStart>
                     <Date>2013-09-12</Date>
                     <Time>09:31:23</Time>
                     <TimeZone>UTC</TimeZone>
                  </TimeStart>

               </CTicket>
            </Body>
         </v1:CreateConsTicketRequest>
      </v1:create>
   </soapenv:Body>
</soapenv:Envelope>

Java client code snippet for creating a SOAP security header:

public static SOAPHeaderBlock getHeaders(String usernameTxt,
            String passwordTxt) {

        LOGGER.debug("Inside getHeaders");
        String WS_SEC_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
        SOAPFactory soapFact = OMAbstractFactory.getSOAP12Factory();
        OMNamespace ns = soapFact.createOMNamespace(WS_SEC_NS, "wsse");
        OMNamespace nsu = soapFact.createOMNamespace(WS_SEC_NS, "wsu");             //try
        SOAPHeaderBlock wssHeader = soapFact.createSOAPHeaderBlock("Security",
                ns);
        OMElement usernameToken = soapFact.createOMElement("UsernameToken", ns);
        OMElement username = soapFact.createOMElement("Username", ns);
        OMElement password = soapFact.createOMElement("Password", ns);
        OMElement nonce = soapFact.createOMElement("Nonce", ns);
        OMElement created = soapFact.createOMElement("Nonce", nsu);


        LOGGER.info("getHeaders: set the WS-security header values");
        username.setText(usernameTxt);


        UUID randomId = UUID.randomUUID();
        String phrase = String.valueOf(randomId);
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA1");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        md.update(phrase.getBytes());
        byte[] byteNonce = md.digest();
        //String nonceHash = String.valueOf(BytesToHex.bytesToHex(byteNonce));
        String nonceHash = String.valueOf(Base64.encodeBase64(byteNonce));
        nonce.setText(nonceHash);

        Date currentTimestamp = new Date();
        String currentTs = String.valueOf(currentTimestamp);
        created.setText(currentTs);

        md.update((nonceHash+currentTs+passwordTxt).getBytes());
        byte[] bytePasswordcode = md.digest();
        String passwordHash = String.valueOf(Base64.encodeBase64(bytePasswordcode));
        //String passwordHash = String.valueOf(BytesToHex.bytesToHex(bytePasswordcode));

        password.setText(passwordHash);

        password.addAttribute(WSConstants.PASSWORD_TYPE_ATTR,
                WSConstants.PASSWORD_DIGEST, null);
        nonce.addAttribute(WSConstants.NONCE_LN, WSConstants.BINARY_TOKEN_LN, null);

        usernameToken.addChild(username);
        usernameToken.addChild(password);
        usernameToken.addChild(nonce); //nonce added
        usernameToken.addChild(created);
        wssHeader.addChild(usernameToken);
        System.out.println(String.valueOf(usernameToken)); //remove
        return wssHeader;
    }

Problem:

I can generate a request and an endpoint, but I get the following exception:

org.apache.axis2.AxisFault: An exception occurred in WSSecuritySOAPHandler.
com.sun.xml.wss.XWSSecurityException:
com.sun.xml.wss.XWSSecurityException:
com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException: It should be divisible by four
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:531)
    at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:375)
    at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:421)
    at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
    at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)

The following is a comparison between the UsernameToken from SaopUI and the Java client: there is some difference. Should this be relevant to my exclusion? please indicate it.

From SaopUI (which works fine):

<wsse:UsernameToken wsu:Id="UsernameToken-14"><wsse:Username>sams</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">YDtfm04egjBgzWM9Mu/pAQqh6Lg=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">KCveDnb6e59NVOlmmP2KEg==</wsse:Nonce>
<wsu:Created>2015-05-12T17:13:48.457Z</wsu:Created></wsse:UsernameToken>

Java ( ):

<wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:Username>sams</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">[B@6950e31</wsse:Password>
<wsse:Nonce Nonce="BinarySecurityToken">e8c9d3bce1fd72994e4813367cf3707afb707b75</wsse:Nonce><wsu:Nonce xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">Wed May 13 11:16:27 EDT 2015</wsu:Nonce></wsse:UsernameToken>

Expectation: , Digest, , , . -, , .

+4

All Articles