SOAP XML WSS4J Verification

Hello Apigee Team,

We have the SOAP XML (Changed values ) for demo.  Want to verify the validity of the certificate of the SOAP Message and extract the  SOAP Body . I referred the below link https://github.com/DinoChiesa/Apigee-Java-WsSec-Signature-2 

and Build the java jars using maven build. 

I Created a simple policy .. and added the below Java Call out. 

It works.. 🙂 

 

 

 

My question is i tried to change DigestValue, BinarySecurityToken values, things are still getting passed.  It should not because even if one small thing is changed, the verification shoould fail. But its not failing 🙂 Why is it so?? 

Java Callout :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout continueOnError="false" enabled="true" name="Java-Callout-1">
<DisplayName>Java Callout-1</DisplayName>
<Properties>
<Property name="source">message.content</Property>
</Properties>
<ClassName>com.google.apigee.callouts.wssecdsig.Validate</ClassName>
<ResourceURL>java://apigee-wssecdsig-20210721-2.jar</ResourceURL>
</JavaCallout>

SOAP Message 

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="wssecurity_signature_id_21">
<wsu:Created>2022-02-02T23:47:12.258Z</wsu:Created>
<wsu:Expires>2022-02-02T23:52:12.258Z</wsu:Expires>
</wsu:Timestamp>
<wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="x509bst_22" 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">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</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<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="soapenv wsse ds " />
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#wssecurity_signature_id_20">
<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="#default soapenv wsu ns2 " />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>sfF5Sh8vtxmRCZzgaZRJJBFBe9c=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#wssecurity_signature_id_21">
<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="soapenv wsu wsse " />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>5A3PPyCM0fa7ONWAn1Oo32Z73bE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>KavQeKq8aLrHK56NwrK7RXuwEDMqOVmcvopYjpkhzkv5EOW5Hkn/h6Me6VXJOUiLmwdqoCpFAyMmqxu7EN7wZn6+bMvdAbHvAPtthMe/6Hq0ejJsyr4r5ooqPLoiNBWgBZIbElo7UOBJ4q66bqlRDt+NKWkW5JZTI2yN6KpVDUo5rgi0WG0whFZEGCIS3Ho4Z7ZUEvW3GDZ+x2UDZEmetyRtbCt8+OEcoTGunTjXJKiW+GDGkClNQOcg1dyagtuAoXjPrB8vIpihM02jv5N5tY3fSlxTaLXNsMplU2F2jHzDdILEjDtfo079lbUQufKKFQzaaPs/L7YeFcqVn5657w==</ds:SignatureValue>
<ds:KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference URI="#x509bst_22" 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>
</soapenv:Header>
<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="wssecurity_signature_id_20">
<ns2:saveCompany xmlns:ns2="http://raj.vai.com/ftf/admin/ws/company/xsd/" xmlns="http://dt.admin.ftf.raj.vai.com/xsd">
<ns2:saveCompanyRequest>
<companyProfile>
<addressLine1>STN MAIN</addressLine1>
<addressLine2 />
<city>COBOURG</city>
<companyName>KKKZ</companyName>
<country>CA</country>
<industryType>GOV</industryType>
<postalCode>445</postalCode>
<primaryContactEmail>eee@z</primaryContactEmail>
<primaryContactName></primaryContactName>
<primaryContactNumber>5567342</primaryContactNumber>
<state>ON</state>
<status>A</status>
</companyProfile>
</ns2:saveCompanyRequest>
</ns2:saveCompany>
</soapenv:Body>
</soapenv:Envelope>

 

 

 

Solved Solved
0 11 799
1 ACCEPTED SOLUTION

Thanks for the guidance Dino. I was trying to format the XML from the 3rd party system and then trying format it for readability . By formatting it, the hash was different and the verification was failed. I was now able to rectify the issue and it verification worked fine   

View solution in original post

11 REPLIES 11

Are you expecting a fault? That callout does not always throw a fault when the signature does not verify.

There is a property you must set in order to get a fault. It's described in the README

throw-fault-on-invalid

optional. true or false, defaults to false. Whether to throw a fault when the signature is invalid, or when validation fails for another reason (wrong elements signed, lifetime exceeds max, etc).

If you do not set this to true, then the policy will succeed, but you can look at the wssec_valid context variable to see the status, and the wssec_error to see the cause of any error.

Also you need to specify a set of one or more cert thumbprints to validate against. The callout forces you to specify this. If it did not, if the callout merely validated the signature on the document, then ANYONE could generate a signature with a random certificate, and the callout would check the signature, find that it's good, and allow it. That's not what you want. You want to ensure that a particular party signed the document - that's what accept-thumbprints does .

Your policy configuration should look like this:

 

<JavaCallout continueOnError="false" enabled="true" name="Java-Callout-1">
  <Properties>
    <Property name="throw-fault-on-invalid">true</Property>
    <Property name="source">message.content</Property>
    <Property name="accept-thumbprints">CERT_THUMBPRINT_HERE</Property>
  </Properties>
  <ClassName>com.google.apigee.callouts.wssecdsig.Validate</ClassName>
  <ResourceURL>java://apigee-wssecdsig-20210721-2.jar</ResourceURL>
</JavaCallout>

 

Thanks for the suggestion. I tried your solution .

Now i am getting below error for a valid SOAP Message . I updated the  below properties

<Property name="throw-fault-on-invalid">true</Property>
<Property name="accept-thumbprints">***</Property>

Please  the error

 

 

 

{
    "fault": {
        "faultstring": "Execution returned an error result",
        "detail": {
            "errorcode": "flow.execution.ExecutionReturnedFailure"
        }
    }
}

 

 

check the error message contained in the wssec_error context variable.

Also you may wish to read the README associated to the callout. All of the information I am relaying to you here, is in that document.

Could you pls let me know on how to check that .? I did not find any guide to check the context variable value incase of failure.

Sure. Check the doc page here: https://cloud.google.com/apigee/docs/api-platform/fundamentals/introduction-flow-variables and also look for the embedded video that describes how to see these variables using the Apigee trace mechanism. 

If you want a quick overview of Tracing, you can also check this out .  The trace capability is called "trace" in the older Apigee Edge, which is what is shown in this screencast. It is called "Debug" in Apigee X or hybrid. It looks and works basically the same way, though. 

Thanks for the Article. I tried to expore the flow variables . Created a JS callout to read the context variable "wssec_error " &  wssec_valid  after the Java Callout. For success calls without setting ("throw-fault-on-invalid"  &  accept-thumbprints) ,  I was able to output these variable values by print in javascript. But when the Java fails when i set ("throw-fault-on-invalid"  &  accept-thumbprints) , the control does not come to JS callout at all. Not sure why . Can you help with this . On Java Callout, Continue is also error is true. 

Please find below the details .

 

 

var wssec_valid=context.getVariable('wssec_valid');
var wssec_error =context.getVariable('wssec_error');

print("hello"+wssec_valid);
print("hellooo"+wssec_error);
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<JavaCallout continueOnError="true" enabled="true" name="Java-Callout-1">
    <Properties>
        <Property name="source">message.content</Property>
        <Property name="throw-fault-on-invalid">true</Property>
        <Property name="accept-thumbprints">****</Property>
    </Properties>
    <ClassName>com.google.apigee.callouts.wssecdsig.Validate</ClassName>
    <ResourceURL>java://apigee-wssecdsig-20210721-2.jar</ResourceURL>
</JavaCallout>

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ProxyEndpoint name="default">
    <PreFlow name="PreFlow">
        <Request>
            <Step>
                <FaultRules/>
                <Name>Java-Callout-1</Name>
            </Step>
            <Step>
                <Name>JavaScript-1</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>
    <Flows/>
    <PostFlow name="PostFlow">
        <Request/>
        <Response/>
    </PostFlow>
    <HTTPProxyConnection>
        <BasePath>/flowv</BasePath>
    </HTTPProxyConnection>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
    </RouteRule>
</ProxyEndpoint>

 

If you use throw-fault-on-invalid, then the proxy goes into Fault Handling.

The subsequent policies do not get executed. This is expected behavior of an Apigee API proxy.

For some background, see here.

The summary is

  • use throw-fault-on-invalid = true if you want to use the fault handling approach that is built-in to Apigee (FaultRules, etc.), when the signature is invalid.
  • do not use that property if you want your subsequent policies(the JS policy, etc) to examine the status  of the WSSec callout, even in the case of invalid signature.

Thanks for clarifying it. From the security purpose of integration with client, we need to verify the signature. I dont want to skip the signature verification. We are currently using a 3rd party API Proxy vendor for the SOAP X509 certificate verification. We are now migrating this to Apigee . I have added all of the valid properties for java call out .

Trace: 

sig_verify.PNG

<Properties>
    <Property name="throw-fault-on-invalid">true</Property>
    <Property name="source">message.content</Property>
    <Property name="accept-thumbprints">CERT_THUMBPRINT_HERE</Property>
  </Properties>

 But still the verification is failing. However the same document is been able to verify by the 3rd party API Gateway vendor successfully . I am not sure on how do i proceed futher on this. 

We basically need two things.

1) Verify the Signature of the SOAP Message

2) Remove the Signature and then pass only the SOAP Body to the endpoint 

 

From the security purpose of integration with client, we need to verify the signature. I dont want to skip the signature verification.

OK Good! That's a good practice! The WS-Sec callout never skips the verification of the signature, so you're in good shape. The property we have been discussing, throw-fault-on-invalid, does not affect whether the callout verifies the signature. It affects what the callout DOES when the signature is not valid. I have explained this in some detail here, and also You can read about this in the fine documentation in the README file. I won't explain it again, since i've explained it several times already.

But still the verification is failing. However the same document is been able to verify by the 3rd party API Gateway vendor successfully . I am not sure on how do i proceed futher on this.

I'm sorry you're having trouble getting the results you're expecting. if you feel comfortable, you can send to me the signed SOAP document, and I'll see if I can figure out what's going on here. Reach me at dchiesa@google.com. Or, if you have a SOAPUI project that sends the request, you can share that with me too. I'd like to help.

Thanks for the guidance Dino. I was trying to format the XML from the 3rd party system and then trying format it for readability . By formatting it, the hash was different and the verification was failed. I was now able to rectify the issue and it verification worked fine   

Great! Thank you for confirming.