1

I am trying to make a web service call to an external system. The Gateway to the application server needs a soap signed request (WSS Security). The service provider confirmed authetication happens only through the certificate. No Username and Password is needed.

My Efforts - I have tried the below approach to establish the connection.

  1. Parsing the WSDL file and generating the corresponding Schema and Stub apex classes. When using the generated stub methods along with the Client provided CA signed certificate to make the callout, I am receiving “Policy Falsified” error message.

  2. I then tried making a callout using the "Http Request" object by adding the CA signed certificate to the “setClientCertificateName” parameter of the request but we received the same error message i.e. “Policy Falsified” error message.

Above approach did not generate the Header with sse:Security tags. So I moved towards below approach.

  1. I again used the Http Request object for make the call out but created a Signed Soap message and added to the body of the request. The private key was also converted to pkcs8 and added it as a part of signed soap message.

After making the callout, I received the same error message i.e. “Policy Falsified” error message.

The exact error message is:<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <soapenv:Fault> <faultcode>soapenv:Server</faultcode> <faultstring>Policy Falsified</faultstring> <faultactor>Endpoint</faultactor> <detail> <l7:policyResult status="Bad Request" xmlns:l7="http://www.layer7tech.com/ws/policy/fault"/> </detail> </soapenv:Fault> </soapenv:Body> </soapenv:Envelope>

Could you please help me in understanding if my approach is in the correct direction.

I also believe in going with approach 3, but my soap signed message is incorrect (Error message says bad request), but my I lack knowledge to pin point my mistakes. need help here as well.

My signed soap message snippet looks as below:

    //RSA Private Key
    String keyPkcs8 =   'pkcs8 Key';      

    // create Signature Digest
    String soapBodyContent ='XML Body tag';
    Blob blobDigest = Crypto.generateDigest('SHA1',Blob.valueOf(soapBodyContent));
    String base64Digest = EncodingUtil.base64Encode(blobDigest);

    // construct Security/Signature/SignedInfo/Reference
    String ds_Reference = '';
    ds_Reference += '<ds:Reference URI="#msgBody">';
    ds_Reference += '<ds:Transforms>';
    ds_Reference += '<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">';
    ds_Reference += '<ec:InclusiveNamespaces PrefixList="" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>';
    ds_Reference += '</ds:Transform>';
    ds_Reference += '</ds:Transforms>';
    ds_Reference += '<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>';
    ds_Reference += '<ds:DigestValue>' +base64Digest +'</ds:DigestValue>';
    ds_Reference += '</ds:Reference>'; 

    // construct Security/Signature/SignedInfo
    String ds_SignedInfo = '<ds:SignedInfo>';
    ds_SignedInfo += '<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">';
    ds_SignedInfo += '<ec:InclusiveNamespaces PrefixList="soapenv" ';
    ds_SignedInfo += 'xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>';
    ds_SignedInfo += '</ds:CanonicalizationMethod>';
    ds_SignedInfo += '<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>';
    ds_SignedInfo += ds_Reference;
    ds_SignedInfo += '</ds:SignedInfo>';

    // generate signature value value with pkcs8 private key
    String algorithmName = 'RSA-SHA1';
    Blob privateKey = EncodingUtil.base64Decode(keyPkcs8);    
    Blob sigBlob = Blob.valueOf(ds_SignedInfo);
    Blob signatureValue = Crypto.sign(algorithmName, sigBlob, privateKey);
    String signatureValueString = EncodingUtil.base64Encode(signatureValue);

    // construct Security/Signature/SignatureValue
    String ds_SignatureValue ='';
    ds_SignatureValue = '<ds:SignatureValue>' +signatureValueString +'</ds:SignatureValue>';

    // construct Security/Signature/KeyInfo
    String ds_KeyInfo ='';
    ds_KeyInfo += '<ds:KeyInfo Id="I gave Some Random Id">';
    ds_KeyInfo += '<wsse:SecurityTokenReference wsu:Id="I gave Some Random Id">';
    ds_KeyInfo += '<ds:X509Data>';
    ds_KeyInfo += '<ds:X509IssuerSerial>';
    ds_KeyInfo += '<ds:X509IssuerName>Hard coded value as received from a working sample from WS provider</ds:X509IssuerName>';
    ds_KeyInfo += '<ds:X509SerialNumber>Hard coded value as received from a working sample from WS provider</ds:X509SerialNumber>';
    ds_KeyInfo += '</ds:X509IssuerSerial>';
    ds_KeyInfo += '</ds:X509Data>';
    ds_KeyInfo += '</wsse:SecurityTokenReference>';
    ds_KeyInfo += '</ds:KeyInfo>';

    // construct WSSE Header/Security       
    String wsse_Security = '<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">';
    wsse_Security += '<ds:Signature Id="I gave Some Random Id" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">';
    wsse_Security += ds_SignedInfo;
    wsse_Security += ds_SignatureValue;
    wsse_Security += ds_KeyInfo;
    wsse_Security += '</ds:Signature>';
    wsse_Security += '</wsse:Security>';

    // construct full SOAP message
    String soapEnvStart = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">';
    String soapEnvEnd = '</soapenv:Envelope>';

    String soapHeader = '<soapenv:Header>';
    String soapHeaderEnd = '</soapenv:Header>';

    String soapBody = '<soapenv:Body>';
    String soapBodyEnd = '</soapenv:Body>';
    // change the soapBody based on operation invoked

    String reqSoap= soapEnvStart 
                +soapHeader 
                    +wsse_Security 
                +soapHeaderEnd 
                +soapBody 
                    +soapBodyContent 
                +soapBodyEnd
            +soapEnvEnd;

    System.debug(reqSoap);
    HttpRequest req = new HttpRequest();
    req.setEndpoint('Endpoint');
    req.setMethod('POST');
    req.setHeader('Content-Type', 'text/xml');
    req.setHeader('SOAPAction', 'Action');
    req.setBody(reqSoap);

    Http http = new Http();
    HTTPResponse res = http.send(req);
    System.debug(res.getBody());

Please let me know if something else is needed and I will update my post accordingly.

Thanks for your help!!

Your Answer

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

Browse other questions tagged or ask your own question.