2

How to construct a security WSSE header in APEX code to make a SOAP call out? I keep getting this error when trying to execute my request: Web service callout failed: Unable to find header type info forsecurityHeader.

This is the XML that I am trying to reproduce.

<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">
     <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <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:UsernameToken>
  </wsse:Security>

SOAP Object Class:

... public class Soap {
        public SFMC_SOAP_TO_SF_SECURITY.WrapperHeader securityHeader = new SFMC_SOAP_TO_SF_SECURITY.WrapperHeader('USERNAME', 'PASSWORD');
        private String Security_hns = 'Security=http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
        public String endpoint_x = 'HIDDEN FOR PRIVACY';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{'http://exacttarget.com/wsdl/partnerAPI', 'SFMC_SOAP_TO_SF_API'};
        public SFMC_SOAP_TO_SF_API.VersionInfoResponseMsg_element VersionInfo(Boolean IncludeVersionHistory) {
            SFMC_SOAP_TO_SF_API.VersionInfoRequestMsg_element request_x = new SFMC_SOAP_TO_SF_API.VersionInfoRequestMsg_element();
            request_x.IncludeVersionHistory = IncludeVersionHistory;
            SFMC_SOAP_TO_SF_API.VersionInfoResponseMsg_element response_x;
            Map<String, SFMC_SOAP_TO_SF_API.VersionInfoResponseMsg_element> response_map_x = new Map<String, SFMC_SOAP_TO_SF_API.VersionInfoResponseMsg_element>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              'VersionInfo',
              'http://exacttarget.com/wsdl/partnerAPI',
              'VersionInfoRequestMsg',
              'http://exacttarget.com/wsdl/partnerAPI',
              'VersionInfoResponseMsg',
              'SFMC_SOAP_TO_SF_API.VersionInfoResponseMsg_element'}
            );
            response_x = response_map_x.get('response_x');
            return response_x;
        }
public SFMC_SOAP_TO_SF_API.RetrieveResponseMsg_element Retrieve_x(SFMC_SOAP_TO_SF_API.RetrieveRequest RetrieveRequest) {
            SFMC_SOAP_TO_SF_API.RetrieveRequestMsg_element request_x = new SFMC_SOAP_TO_SF_API.RetrieveRequestMsg_element();
            request_x.RetrieveRequest = RetrieveRequest;
            SFMC_SOAP_TO_SF_API.RetrieveResponseMsg_element response_x;
            Map<String, SFMC_SOAP_TO_SF_API.RetrieveResponseMsg_element> response_map_x = new Map<String, SFMC_SOAP_TO_SF_API.RetrieveResponseMsg_element>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              'Retrieve',
              'http://exacttarget.com/wsdl/partnerAPI',
              'RetrieveRequestMsg',
              'http://exacttarget.com/wsdl/partnerAPI',
              'RetrieveResponseMsg',
              'SFMC_SOAP_TO_SF_API.RetrieveResponseMsg_element'}
            );
            response_x = response_map_x.get('response_x');
            return response_x;
} ...

Security Header Class:

    public class SFMC_SOAP_TO_SF_SECURITY 
{

    public class WrapperHeader{

        public WrapperHeader(String username, String password){
            this.header = new SFMC_SOAP_TO_SF_SECURITY.SecurityHeader(username, password);             
        }
        public SFMC_SOAP_TO_SF_SECURITY.SecurityHeader header;
        private String[] apex_schema_type_info = new String[]{'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','true','false'};
        private String[] field_order_type_info = new String[]{'Header'}; 
    }

    public class SecurityHeader{

        public SecurityHeader(String username, String password){
            this.headerPackager = new SFMC_SOAP_TO_SF_SECURITY.SecurityHeaderType(username, password);
        }

        public String wsseNamespace = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
        public SFMC_SOAP_TO_SF_SECURITY.SecurityHeaderType headerPackager;
        private String[] wsseNamespace_att_info = new String[]{'xmlns:wsse'};               
        private String[] apex_schema_type_info = new String[]{'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','true','false'};
        private String[] field_order_type_info = new String[]{'Security'}; 

    }

    // SecurityHeaderType Class
    public class SecurityHeaderType 
    {       
        // Constructor for SecurityHeaderType used to pass in username and password parameters and instantiate the UsernameToken object     
        public SecurityHeaderType(String username, String password)
        {
            this.UsernameToken = new SFMC_SOAP_TO_SF_SECURITY.UsernameToken(username, password);
        }

        public String wsuNamespace = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd';              
        public SFMC_SOAP_TO_SF_SECURITY.UsernameToken UsernameToken;
        private String[] UsernameToken_type_info = new String[]{'UsernameToken','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','UsernameToken','1','1','false'};
        private String[] wsuNamespace_att_info = new String[]{'xmlns:wsu'};               
        private String[] apex_schema_type_info = new String[]{'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','true','false'};
        private String[] field_order_type_info = new String[]{'UsernameToken'};
    }


    public class UsernameToken {
        // Constructor for UsernameToken used to pass in username and password parameters
        public UsernameToken(String username, String password)
        {
            this.Username = username;
            this.Password = new password_e(password);
        }

        public String Username;
        public password_e Password;
        private String[] Username_type_info = new String[]{'Username','http://www.w3.org/2001/XMLSchema','string','0','1','false'};
        private String[] Password_type_info = new String[]{'Password','http://www.w3.org/2001/XMLSchema','string','0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','true','false'};
        private String[] field_order_type_info = new String[]{'Username','Password'};

    }

        public class password_e{
            public password_e(String password) {
                this.password = password;
                type = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText';             
        }

            public String password;
            public string type; 
            public String[] type_att_info = new String[]{'Type'};        
            private String[] password_type_info = new String[]{'Password','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText','string','1','1','false'};
            private String[] apex_schema_type_info = new String[]{'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','true','false'};
            private String[] field_order_type_info = new String[]{'password'};
    }

}
1

One alternative way to get this working is stop using the out of box generated apex class and instead hand craft the required SOAP request and make an https callout using http system class.

The out of box functionality today t hat converts WSDL to apex does not support wss security.

Check the post here (Forming SOAP header through apex class if the WSDL provided has no information regarding the header)

2
  • 1
    Thank you for your response. Yes, I know that the fact that Salesforce currently do not support WS headers from the WSDL2Apex class generated... but I do intend to modify such class in order to make it work (as seen above). If I use HTTP Callout it would be extremely difficult to maintain and XML parsing would be a nightmare. – callmejoe Jan 5 '20 at 10:22
  • you will need to proxy the request sent from apex and watch the XML payload to see whats going on. It will be a trial and error till you get it right .I am off the opinion that it is actually easier to maintain the string format as one would then not need any tool to debug this . – Mohith Shrivastava Jan 5 '20 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.