Subject: Issue with Secured SOAP Web Service Calls Using Metro Library (webservices-rt.jar 2.4.9 version)
Description:
We have a product module that supports access to external SOAP-based web services, including secured web services. This module utilizes the Metro web services library for implementing web service calls and responses.
A partner reported an issue where the web service caller configured in our product was throwing errors when executing requests to a fully secured web service. The customer encountered the following errors:
WSSTUBE0025: Fehler bei der Prüfung der Sicherheit in der eingehenden Nachricht.
WSS1717: Fehler bei Ausführung der Digest-Prüfung von Nachrichtentext/Payload
Upon investigation, we identified the root cause of the issue to be within the Metro library itself. Below is the WSDL used by the customer:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsc="http://localhost:8000/test/ws/1698157283592/Webservice111"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
targetNamespace="http://localhost:8000/test/ws/1698157283592/Webservice111">
<!-- Types section -->
<types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="http://localhost:8000/test/ws/1698157283592/Webservice111">
<xs:element name="getBalancing" type="xs:string"/>
<xs:element name="getBalancingResponse" type="xs:string"/>
</xs:schema>
</types>
<!-- Messages -->
<message name="Header">
<part name="messageAddressing" element="wsc:MessageAddressing"/>
</message>
<message name="getBalancingRequest">
<part name="parameters" element="wsc:getBalancing"/>
</message>
<message name="getBalancingResponse">
<part name="parameters" element="wsc:getBalancingResponse"/>
</message>
<!-- PortType -->
<portType name="WebservicePortType">
<operation name="getBalancing">
<input message="wsc:getBalancingRequest"/>
<output message="wsc:getBalancingResponse"/>
</operation>
</portType>
<!-- Binding -->
<binding name="WebserviceBinding" type="wsc:WebservicePortType">
<wsp:PolicyReference URI="#BaseSecurityPolicy" required="false"/>
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getBalancing">
<soap:operation soapAction="getBalancing"/>
<input>
<soap:header message="wsc:Header" part="messageAddressing" use="literal"/>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<!-- Service -->
<service name="Webservice">
<port name="WebservicePort" binding="wsc:WebserviceBinding">
<soap:address location="localhost:8000/test/ws/Webservice"/>
</port>
</service>
<!-- Policies -->
<wsp:Policy wsu:Id="BaseSecurityPolicy">
<sp:AsymmetricBinding>
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
<wsp:Policy>
<sp:RequireKeyIdentifierReference/>
<sp:WssX509V3Token10/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
<wsp:Policy>
<sp:RequireKeyIdentifierReference/>
<sp:WssX509V3Token10/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:RecipientToken>
<sp:AlgorithmSuite signatureAlgorithm="SHA256withRSA">
<wsp:Policy>
<sp:Basic256Sha256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:OnlySignEntireHeadersAndBody/>
</wsp:Policy>
</sp:AsymmetricBinding>
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier/>
</wsp:Policy>
</wsp:Policy>
</definitions>
Root Cause Analysis:
-
When an empty security policy (EmptySecurityPolicy) is configured in the WSDL, the Metro library expects a Timestamp policy as the default. However, in response, the provider sends a Signature policy, causing a mismatch and resulting in the above errors.
-
After resolving the initial issue, we encountered another error:
WSS1717: Fehler bei Ausführung der Digest-Prüfung von Nachrichtentext/Payload
This occurred because the provider sends a large response in chunked format. The Metro library calculates the digest differently, leading to a mismatch and failure.
Fixes Implemented:
-
Handling Security Policy Mismatch:
- We modified the Metro library to allow both
TimestampPolicy and SignaturePolicy: Class name- MessagePolicyVerifier
private boolean checkAllowExtraTimestamp(MessagePolicy inferredSecurityPolicy) {
if (inferredSecurityPolicy.size() > 1) {
return false;
}
SecurityPolicy pol = null;
try {
pol = inferredSecurityPolicy.get(0);
} catch (Exception ex) {
// Ignore exception
}
return pol instanceof TimestampPolicy || pol instanceof SignaturePolicy;
}
-
Handling Digest Mismatch Due to Chunked Response:
- A system property (
digest.value.bypass) was introduced to bypass digest verification at the Metro library level: Class name-StreamingPayLoadDigester.java and method accept
if (System.getProperty("digest.value.bypass") != null && System.getProperty("digest.value.bypass").equals("false")) {
if (!Arrays.equals(originalDigest, calculatedDigest)) {
XMLSignatureException xe = new XMLSignatureException(LogStringsMessages.WSS_1717_ERROR_PAYLOAD_VERIFICATION());
logger.log(Level.SEVERE, LogStringsMessages.WSS_1717_ERROR_PAYLOAD_VERIFICATION(), xe);
throw new WebServiceException(xe);
} else {
if (logger.isLoggable(Level.FINEST)) {
if (!payLoad) {
logger.log(Level.FINEST, "Digest verification of Body was successful");
} else {
logger.log(Level.FINEST, "Digest verification of PayLoad was successful");
}
}
}
} else {
System.setProperty("digest.value.bypass", "false");
}
With these fixes, we have patched **webservices-rt.jar (version 2.4.9)** and are now using it. The customer is successfully receiving and processing secured SOAP responses.
### Requests & Questions
1. Is there a more **generic and robust way** to handle these errors at the **Metro framework** level? If so, can the **Metro team** incorporate these fixes into the official **Metro library release (version 2.4.9 or later)?**
2. If contributions are allowed, we can make the changes specific to our needs and **raise a PR**. Would this be a good and recommended approach?
### Acknowledgment & Thanks
We appreciate your support in resolving these issues and look forward to your recommendations.
🙏 A big thank you to the **[eclipse-ee4j](https://github.com/eclipse-ee4j)/[metro-wsit](https://github.com/eclipse-ee4j/metro-wsit) team** for your continuous support and maintenance! Your efforts in keeping this project running smoothly are truly appreciated.
Subject: Issue with Secured SOAP Web Service Calls Using Metro Library (webservices-rt.jar 2.4.9 version)
Description:
We have a product module that supports access to external SOAP-based web services, including secured web services. This module utilizes the Metro web services library for implementing web service calls and responses.
A partner reported an issue where the web service caller configured in our product was throwing errors when executing requests to a fully secured web service. The customer encountered the following errors:
Upon investigation, we identified the root cause of the issue to be within the Metro library itself. Below is the WSDL used by the customer:
Root Cause Analysis:
When an empty security policy (
EmptySecurityPolicy) is configured in the WSDL, the Metro library expects a Timestamp policy as the default. However, in response, the provider sends a Signature policy, causing a mismatch and resulting in the above errors.After resolving the initial issue, we encountered another error:
This occurred because the provider sends a large response in chunked format. The Metro library calculates the digest differently, leading to a mismatch and failure.
Fixes Implemented:
Handling Security Policy Mismatch:
TimestampPolicyandSignaturePolicy: Class name- MessagePolicyVerifierHandling Digest Mismatch Due to Chunked Response:
digest.value.bypass) was introduced to bypass digest verification at the Metro library level: Class name-StreamingPayLoadDigester.java and method accept} else {
System.setProperty("digest.value.bypass", "false");
}