I have another problem with Counter Signature. This time I forced it to work... almost.
Bellow is the copy of the Signature:
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="xmldsig-33fefaee-5877-4bcb-8ee2-782d23424a86">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference Id="xmldsig-33fefaee-5877-4bcb-8ee2-782d23424a86-ref0" URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>tYHwvIGQOhMyX1gAfjLqUwxPaQVEbr9b5aVRNb1GLZA=</ds:DigestValue>
</ds:Reference>
<ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-33fefaee-5877-4bcb-8ee2-782d23424a86-signedprops">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>60WWYTr+S6Na75HS+IDlenFiSImMmDdJGn9VH/Jm00o=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue Id="xmldsig-33fefaee-5877-4bcb-8ee2-782d23424a86-sigvalue">
cbJxI3IQOBZqcsGTCl/kgBR3aqS876ck9glukj4gJh4QggnUW46+eb3yucrtxojyF4W9jwqhVmwP
IYUJpKjgDnRbIIrVKWYiLpQV70MqWsV8DKPLdzz7vofDZuWQAsKSlEQqzkd1JMQf/HkgDK0PbXCX
iXBCye/+W1eshR/byrU=
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIICODCCAaGgAwIBAgIBFjANBgkqhkiG9w0BAQUFADA0MQswCQYDVQQGEwJQTDEOMAwGA1UEChMF
cGVrYW8xFTATBgNVBAMUDENBX1BFS0FPX1NTTDAeFw0xNDA2MjYxMDU2MzdaFw0xNTA2MjYxMDU2
MzdaMF8xCzAJBgNVBAYTAlBMMQ4wDAYDVQQKEwVQRUtBTzEWMBQGA1UECxMNUGVrYW9CSVpORVMy
NDEoMCYGA1UEAxQfQkFSVE9TWiBK01pFRiBKQVJLT1dTS0ksIDcxMDU4NjCBnzANBgkqhkiG9w0B
AQEFAAOBjQAwgYkCgYEA4ZlPMdEYmwlsy1wFoGTVGShW6nPyHHeAVm2r+nuin9ZOeRFlDl+PPyTJ
oZ6avZKCyt1R3o4oju7LmKQhlCsSR88CZrXF0vPovZjthblvrUJ742RC4laoiBSR9hZIg4CWorF1
rk3/bHobz3ZLCLg+P64RKmTI7WYrgCeHsBJMPfECAwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8E
BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAiJqNtI1ml8OKSnB5
PzbhfCJlK+12SPFX6GcQkO6dF7ezNFzzC9bcD6MOkAEnR4IfEkD3CIl8Jx8v29XV/eCes3gDa9Z6
OSzVZpMBDFQicWtLfch7Xmh/KS2GFelbkiqHHf/UKfhcN32fsV86WOP6DOb8XMJLrcgmMz0bxvl3
yfM=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<ds:Object>
<xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#" Target="#xmldsig-33fefaee-5877-4bcb-8ee2-782d23424a86">
<xades:SignedProperties Id="xmldsig-33fefaee-5877-4bcb-8ee2-782d23424a86-signedprops">
<xades:SignedSignatureProperties>
<xades:SigningTime>2014-07-08T15:14:22.357+02:00</xades:SigningTime>
<xades:SigningCertificate>
<xades:Cert>
<xades:CertDigest>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>XmRm5R3UpnVKBPiumnYVL6TXgnqCsbk0XF/JwA5he4c=</ds:DigestValue>
</xades:CertDigest>
<xades:IssuerSerial>
<ds:X509IssuerName>DELETED</ds:X509IssuerName>
<ds:X509SerialNumber>22</ds:X509SerialNumber>
</xades:IssuerSerial>
</xades:Cert>
</xades:SigningCertificate>
</xades:SignedSignatureProperties>
<xades:SignedDataObjectProperties>
<xades:CommitmentTypeIndication>
<xades:CommitmentTypeId>
<xades:Identifier>http://uri.etsi.org/01903/v1.2.2#ProofOfApproval</xades:Identifier>
<xades:Description>Indicates that the signer has approved the content of the signed data object</xades:Description>
</xades:CommitmentTypeId>
<xades:ObjectReference>#xmldsig-33fefaee-5877-4bcb-8ee2-782d23424a86-ref0</xades:ObjectReference>
</xades:CommitmentTypeIndication>
</xades:SignedDataObjectProperties>
</xades:SignedProperties>
<xades:UnsignedProperties>
<xades:UnsignedSignatureProperties>
<xades:CounterSignature>
<ds:Signature Id="xmldsig-d848b745-aee3-476c-8b93-6ceafa34eaea" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference Id="xmldsig-d848b745-aee3-476c-8b93-6ceafa34eaea-ref0" URI="#xmldsig-33fefaee-5877-4bcb-8ee2-782d23424a86-sigvalue">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>5bEeIUwcOzwar60fKN7CQrkhukdl1twK+h/J3iLgSso=</ds:DigestValue>
</ds:Reference>
<ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#xmldsig-d848b745-aee3-476c-8b93-6ceafa34eaea-signedprops">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>VpjF9Ag6SUwezpv1FL/wSgLr5eBme67r3mXz9gqXegE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue Id="xmldsig-d848b745-aee3-476c-8b93-6ceafa34eaea-sigvalue">
0V/J3Tgooevc0vkLAkd/2OGMN1mSvfy/Xn12iBTDEejcQR7c9JR96RIQpZGkYw23tufBf1uReLkf
R7mdHuOWIVeDJjPZYL+l9rP7dv9ceJMtjOxUUgY/codnb5yRv0LnhBkPVBBiEfIogqzsgSM99Rpw
byiAPW6jZT2Qb4MIrlc=
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIICODCCAaGgAwIBAgIBFjANBgkqhkiG9w0BAQUFADA0MQswCQYDVQQGEwJQTDEOMAwGA1UEChMF
cGVrYW8xFTATBgNVBAMUDENBX1BFS0FPX1NTTDAeFw0xNDA2MjYxMDU2MzdaFw0xNTA2MjYxMDU2
MzdaMF8xCzAJBgNVBAYTAlBMMQ4wDAYDVQQKEwVQRUtBTzEWMBQGA1UECxMNUGVrYW9CSVpORVMy
NDEoMCYGA1UEAxQfQkFSVE9TWiBK01pFRiBKQVJLT1dTS0ksIDcxMDU4NjCBnzANBgkqhkiG9w0B
AQEFAAOBjQAwgYkCgYEA4ZlPMdEYmwlsy1wFoGTVGShW6nPyHHeAVm2r+nuin9ZOeRFlDl+PPyTJ
oZ6avZKCyt1R3o4oju7LmKQhlCsSR88CZrXF0vPovZjthblvrUJ742RC4laoiBSR9hZIg4CWorF1
rk3/bHobz3ZLCLg+P64RKmTI7WYrgCeHsBJMPfECAwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8E
BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAiJqNtI1ml8OKSnB5
PzbhfCJlK+12SPFX6GcQkO6dF7ezNFzzC9bcD6MOkAEnR4IfEkD3CIl8Jx8v29XV/eCes3gDa9Z6
OSzVZpMBDFQicWtLfch7Xmh/KS2GFelbkiqHHf/UKfhcN32fsV86WOP6DOb8XMJLrcgmMz0bxvl3
yfM=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<ds:Object>
<xades:QualifyingProperties Target="#xmldsig-d848b745-aee3-476c-8b93-6ceafa34eaea" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#">
<xades:SignedProperties Id="xmldsig-d848b745-aee3-476c-8b93-6ceafa34eaea-signedprops">
<xades:SignedSignatureProperties>
<xades:SigningTime>2014-07-08T15:17:53.877+02:00</xades:SigningTime>
<xades:SigningCertificate>
<xades:Cert>
<xades:CertDigest>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>XmRm5R3UpnVKBPiumnYVL6TXgnqCsbk0XF/JwA5he4c=</ds:DigestValue>
</xades:CertDigest>
<xades:IssuerSerial>
<ds:X509IssuerName>DELETED</ds:X509IssuerName>
<ds:X509SerialNumber>22</ds:X509SerialNumber>
</xades:IssuerSerial>
</xades:Cert>
</xades:SigningCertificate>
</xades:SignedSignatureProperties>
</xades:SignedProperties>
</xades:QualifyingProperties>
</ds:Object>
</ds:Signature>
</xades:CounterSignature>
</xades:UnsignedSignatureProperties>
</xades:UnsignedProperties>
</xades:QualifyingProperties>
</ds:Object>
My JAVA code:
Element signatureNode = (Element)docSource.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature").item(0);
//If signatureNode is null, it means there is no certificate in the file - need to create new Enveloped Certificate.
//If signatureNode is not null, we can extend it with CounterSignature.
if (signatureNode != null)
{
String sigValueId = signatureNode.getAttribute(Constants._ATT_ID);
DataObjectReference sigValueRef = new DataObjectReference('#' + sigValueId)
.withType(CounterSignatureProperty.COUNTER_SIGNATURE_TYPE_URI);
XadesSignatureFormatExtender instance = (XadesSignatureFormatExtender)new XadesFormatExtenderProfile().getFormatExtender();
XMLSignature sig = new XMLSignature(signatureNode, "");
Collection<UnsignedSignatureProperty> usp = new ArrayList<UnsignedSignatureProperty>(1);
usp.add(new CounterSignatureProperty(signer));
instance.enrichSignature(sig, new UnsignedProperties(usp));
}
else
{
DataObjectDesc obj1 = new DataObjectReference("")
.withTransform(new EnvelopedSignatureTransform());
signer.sign(new SignedDataObjects(obj1), docSource.getDocumentElement());
//new Enveloped(signer).sign(docSource.getDocumentElement());
}
When I'm trying to verify this document (with two external applications) I'm getting error saying "Incorrect reference in countersign".
Now I'm investigating what went wrong. Did I miss to reference something?
EDIT:
I checked with different app and I think I got better error message. It is saying exactly:
Signature digest is not equal file digest.
Best Regards
John S.
Related
Here is my XML file content
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:ds=" http://www.w3.org/2000/09/xmldsig#" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:sac="urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2"
xmlns:sbc="urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2" xmlns:sig="urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2">
<ext:UBLExtensions>
<ext:UBLExtension>
<ext:ExtensionURI>urn:oasis:names:specification:ubl:dsig:enveloped:xades</ext:ExtensionURI>
<ext:ExtensionContent>
<sig:UBLDocumentSignatures>
<sac:SignatureInformation>
<cbc:ID>urn:oasis:names:specification:ubl:signature:1</cbc:ID>
<sbc:ReferencedSignatureID>urn:oasis:names:specification:ubl:signature:Invoicesadas</sbc:ReferencedSignatureID>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="signature">
<ds:SignedInfo>
<!-- SOME CONTENT HERE -->
</ds:SignedInfo>
<ds:SignatureValue></ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate></ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<ds:Object>
<xades:QualifyingProperties xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Target="signature">
<xades:SignedProperties Id="xadesSignedProperties">
<xades:SignedSignatureProperties>
<xades:SigningTime>2020-12-25T12:57:51Z</xades:SigningTime>
<xades:SigningCertificate>
<xades:Cert>
<xades:CertDigest>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue> <!-- SOME VALUE HERE --></ds:DigestValue>
</xades:CertDigest>
<xades:IssuerSerial>
<ds:X509IssuerName><!-- SOME VALUE HERE--></ds:X509IssuerName>
<ds:X509SerialNumber><!-- SOME VALUE HERE--></ds:X509SerialNumber>
</xades:IssuerSerial>
</xades:Cert>
</xades:SigningCertificate>
</xades:SignedSignatureProperties>
</xades:SignedProperties>
</xades:QualifyingProperties>
</ds:Object>
</ds:Signature>
</sac:SignatureInformation>
</sig:UBLDocumentSignatures>
</ext:ExtensionContent>
</ext:UBLExtension>
</ext:UBLExtensions>
<!-- SOME CONTENT HERE -->
</Invoice>
I want to retrieve the SignedProperties element with all the in scope xmlns namespaces in the file.
Sample Output that i need looks like
<?xml version="1.0" encoding="UTF-8"?> <xades:SignedProperties **xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:sac="urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2" xmlns:sbc="urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2"
xmlns:sig="urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2"** xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" Id="xadesSignedProperties">
<xades:SignedSignatureProperties>
<xades:SigningTime>020-12-25T12:57:51Z</xades:SigningTime>
<xades:SigningCertificate>
<xades:Cert>
<xades:CertDigest>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue> <!-- SOME VALUE HERE --></ds:DigestValue>
</xades:CertDigest>
<xades:IssuerSerial>
<ds:X509IssuerName> <!-- SOME VALUE HERE --></ds:X509IssuerName>
<ds:X509SerialNumber> <!-- SOME VALUE HERE --></ds:X509SerialNumber>
</xades:IssuerSerial>
</xades:Cert>
</xades:SigningCertificate>
</xades:SignedSignatureProperties>
</xades:SignedProperties>
But I am getting output without the namespaces defined in the root element in the file.
How should i get the element with all the namespaces declared in scope in the XML file?
It seems like you need to apply canonicalization on the extracted xades:SignedProperties node.
You may try to use Canonicalizer from Apache Santuario library and canonicalize the extracted node:
public static byte[] canonicalizeSubtree(final String canonicalizationMethod, final Node node) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
final Canonicalizer c14n = Canonicalizer.getInstance(getCanonicalizationMethod(canonicalizationMethod));
c14n.canonicalizeSubtree(node, baos);
return baos.toByteArray();
} catch (Exception e) {
// some logic here
}
}
For the canonicalization method, it more looks like an "inclusive" canonicalization, e.g.: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" (see ALGO_ID_C14N_WITH_COMMENTS).
all.
I'm interacting with a webservice that's requires signature and policy.
I set up my CXF (3.1.6 wildfly bundled) with binding provider properties, callback handler, keystore ect.
bp.getRequestContext().put(SecurityConstants.CALLBACK_HANDLER, new PasswordCallbackHandler());
bp.getRequestContext().put(SecurityConstants.SIGNATURE_PROPERTIES, MyUtils.class.getClassLoader().getResource("crypto.properties"));
bp.getRequestContext().put(SecurityConstants.SIGNATURE_USERNAME, "client");
CXF takes care to provide all necessary policy defined in the wsdl.
The comunications goes well, I send the request and receive the expected response.
But at this point the CXF Policy validator throws an exception:
org.apache.cxf.ws.policy.PolicyException: These policy alternatives can not be satisfied:
{http://schemas.xmlsoap.org/ws/2005/07/securitypolicy}SignedParts: Soap Body is not SIGNED
at org.apache.cxf.ws.policy.AssertionInfoMap.checkEffectivePolicy(AssertionInfoMap.java:179)
at org.apache.cxf.ws.policy.PolicyVerificationInInterceptor.handle(PolicyVerificationInInterceptor.java:102)
at org.apache.cxf.ws.policy.AbstractPolicyInterceptor.handleMessage(AbstractPolicyInterceptor.java:44)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
This is the contract for the signed parts:
<sp:SignedParts>
<sp:Body />
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo" />
<sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action" />
<sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
This is received response:
...
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="wsse S"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#_5002">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>IirHgSUh19ly5qpPiXKVfMB2tZ4=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_5003">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>8SY6Wz36TUlZtY+31Z5EpESs5JM=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_5004">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>yvxtMZ3SC++ZOv0RPS/Ge9ETGHA=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_5005">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>t/slFuF8/W8sWGrrAuJTmtliCeU=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_5006">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>Cjcz1r8PMjV/04CLrMDpNx+e3ks=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#_3">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<exc14n:InclusiveNamespaces PrefixList="wsu wsse S"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>6htA73nOJBrYMteWrJ9pdag3cA8=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
...
</S:Header>
<S:Body>
<ns2:getCallResponse xmlns:ns2="http://somenamespace/Schemas/" wsu:Id="_5006">
As you can seen there is a reference to the signed part but the ID attribute is not at the body (like for the request) level but on the child tag.
I don't know if this can be the problem, if so is a server side problem but the service is legacy and there's no way to change it.
So my question is: how I can disable the incoming policy validator or the specific assertion on SoapBody?
Thanks
Following the Colm O hEigeartaigh help, this is the resolution implemented.
Properties setup:
// Policy ovveride
Map<QName, SecurityPolicyValidator> validatorMap = new HashMap<>();
validatorMap.put(new QName("http://schemas.xmlsoap.org/ws/2005/07/securitypolicy", "SignedParts"), new FakeSecuredPartsValidator());
bp.getRequestContext().put(SecurityConstants.POLICY_VALIDATOR_MAP, validatorMap);
Fake validator based on the original one in CXF:
public class FakeSecuredPartsValidator implements SecurityPolicyValidator {
private CoverageType coverageType = CoverageType.ENCRYPTED;
/**
* Return true if this SecurityPolicyValidator implementation is capable of validating a
* policy defined by the AssertionInfo parameter
*/
#Override
public boolean canValidatePolicy(AssertionInfo assertionInfo) {
if (coverageType == CoverageType.SIGNED) {
return assertionInfo.getAssertion() != null
&& (SP12Constants.SIGNED_PARTS.equals(assertionInfo.getAssertion().getName())
|| SP11Constants.SIGNED_PARTS.equals(assertionInfo.getAssertion().getName()));
} else {
return assertionInfo.getAssertion() != null
&& (SP12Constants.ENCRYPTED_PARTS.equals(assertionInfo.getAssertion().getName())
|| SP11Constants.ENCRYPTED_PARTS.equals(assertionInfo.getAssertion().getName()));
}
}
/**
* Validate policies, set all as validates
*/
#Override
public void validatePolicies(PolicyValidatorParameters parameters, Collection<AssertionInfo> ais) {
//
// SIGNED_PARTS and ENCRYPTED_PARTS only apply to non-Transport bindings
//
if (isTransportBinding(parameters.getAssertionInfoMap(), parameters.getMessage())) {
return;
}
// Set asserted = true for all Assertions
for (AssertionInfo ai : ais) {
if (ai.isAsserted()) {
// Secured Parts could already have been asserted by one of the other validators, if
// they are a child of a SupportingToken
continue;
}
ai.setAsserted(true);
}
}
private boolean isTransportBinding(AssertionInfoMap aim, Message message) {
AssertionInfo symAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.SYMMETRIC_BINDING);
if (symAis != null) {
return false;
}
AssertionInfo asymAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.ASYMMETRIC_BINDING);
if (asymAis != null) {
return false;
}
AssertionInfo transAis = PolicyUtils.getFirstAssertionByLocalname(aim, SPConstants.TRANSPORT_BINDING);
if (transAis != null) {
return true;
}
// No bindings, check if we are using TLS
TLSSessionInfo tlsInfo = message.get(TLSSessionInfo.class);
if (tlsInfo != null) {
// We don't need to check these policies for TLS
PolicyUtils.assertPolicy(aim, SP12Constants.ENCRYPTED_PARTS);
PolicyUtils.assertPolicy(aim, SP11Constants.ENCRYPTED_PARTS);
PolicyUtils.assertPolicy(aim, SP12Constants.SIGNED_PARTS);
PolicyUtils.assertPolicy(aim, SP11Constants.SIGNED_PARTS);
return true;
}
return false;
}
public CoverageType getCoverageType() {
return coverageType;
}
public void setCoverageType(CoverageType coverageType) {
this.coverageType = coverageType;
}
}
The service is not following the spec, the Body element itself must be signed, and not the child Element as in the request above. However, recent versions of CXF allow you to plug in custom validation logic via the "ws-security.policy.validator.map" JAX-WS property. This is a map which maps a QName to a SecurityPolicyValidator instance. So in your case you can map to SignedParts policy QName to a modified version of the default SecuredPartsPolicyValidator to change the validation logic.
In OpenSAML 2.5, I used the following code to generate a SAML Assertion with Security Certificate details:
Credential signingCredential = sign.getSigningCredential();
Signature signature = null;
try {
DefaultBootstrap.bootstrap();
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
signature = (Signature) Configuration.getBuilderFactory()
.getBuilder(Signature.DEFAULT_ELEMENT_NAME)
.buildObject(Signature.DEFAULT_ELEMENT_NAME);
signature.setSigningCredential(signingCredential);
// This is also the default if a null SecurityConfiguration is
// specified
SecurityConfiguration secConfig = Configuration
.getGlobalSecurityConfiguration();
try {
SecurityHelper.prepareSignatureParams(signature,
signingCredential, secConfig, null);
} catch (SecurityException e) {
e.printStackTrace();
} catch (org.opensaml.xml.security.SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SsoSamlWriter samlWriter = new SsoSamlWriter(ssoData);
Assertion assertion = samlWriter.buildSamlAssertion();
SAML msg extract:
<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#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#514131e4-8ef0-469c-b8b0-a185b874320e">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="xs" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>fmIxhw8sGFU/J3SWDk5BnBCKRog=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>HOHkf...pqj2w==</ds:SignatureValue>
<KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIID...6BS9K
L/SvOZxWrA==</ds:X509Certificate>
</ds:X509Data>
</KeyInfo>
</ds:Signature>
I am trying to update this code to OpenSAML 3.2 and I have been able to get the SAML msg generated, but I don;t know how to attach the detailed security cert data. Does anyone have a code example for adding the SignatureValue and X509Certificate details to the SAML Assertion?
OpenSAML 3.2 Code I have so far:
Credential signingCredential = sign.getSigningCredential();
SsoSamlWriter samlWriter = new SsoSamlWriter(ssoData);
Assertion assertion = samlWriter.buildSamlAssertion();
Signature signature = SAMLUtils.buildSAMLObject(Signature.class);
signature.setSigningCredential(signingCredential);
signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
// Need to supply an org.opensaml.security.credential.Credential;
signature.setSigningCredential(signingCredential);
assertion.setSignature(signature);
try {
XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(assertion).marshall(assertion);
} catch (MarshallingException e) {
throw new RuntimeException(e);
}
try {
Signer.signObject(signature);
} catch (SignatureException e) {
throw new RuntimeException(e);
}
// Wrap assertion in SAML Response
ResponseBuilder responseBuilder = new ResponseBuilder();
Response samlResponse = responseBuilder.buildObject();
// Build an Issuer object
Issuer issuer = SAMLUtils.buildSAMLObject(Issuer.class);
issuer.setValue(ssoIssuerName);
issuer.setSPProvidedID(ssoUrlSuffix);
// Add NameID element to assertion with Oasis Employee SSN
Subject subject = new SubjectBuilder().buildObject();
NameID nameID = new NameIDBuilder().buildObject();
nameID.setValue(empSsn);
nameID.setFormat(NameIDType.X509_SUBJECT);
subject.setNameID(nameID);
assertion.setSubject(subject);
String responseIdStr = UUID.randomUUID().toString();
assertion.setID(responseIdStr);
samlResponse.setID(responseIdStr);
samlResponse.setIssueInstant(new DateTime());
samlResponse.setIssuer(issuer);
samlResponse.setVersion(SAMLVersion.VERSION_20);
samlResponse.setStatus(samlWriter.createStatus());
samlResponse.getAssertions().add(assertion);
ResponseMarshaller marshaller = new ResponseMarshaller();
Element plain = marshaller.marshall(samlResponse);
String samlResponseStr = XMLHelper.nodeToString(plain);
// Remove ds: prefix from <ds:KeyInfo> elements
// stegre => Accomodate bug on CIC side, remove this line eventually
samlResponseStr = samlResponseStr.replaceAll("ds:KeyInfo", "KeyInfo");
System.out.println("");
System.out.println("SAML Response: ");
System.out.println(samlResponseStr);
System.out.println("");
Resulting SAML message:
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response ID="356498c8-036d-41b1-9602-89fa90e40331" IssueInstant="2016-10-12T15:15:23.987Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:Issuer SPProvidedID="OasisAdvantage" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">OasisAdvantage</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</saml2p:Status>
<saml2:Assertion ID="356498c8-036d-41b1-9602-89fa90e40331" IssueInstant="2016-10-12T15:15:20.442Z" Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<saml2:Issuer SPProvidedID="OasisAdvantage">OasisAdvantage</saml2:Issuer>
<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#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#356498c8-036d-41b1-9602-89fa90e40331">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces PrefixList="xsd" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue/>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue/>
</ds:Signature>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName">OasisUser</saml2:NameID>
</saml2:Subject>
<saml2:Conditions NotBefore="2016-10-12T15:15:20.442Z" NotOnOrAfter="2016-10-12T15:20:20.442Z"/>
<saml2:AuthnStatement AuthnInstant="2016-10-12T15:15:20.566Z" SessionNotOnOrAfter="2016-10-12T15:15:20.581Z">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement>
<saml2:Attribute Name="companyid">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">OasisAdvantage</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
</saml2p:Response>
The following code added the computed SignatureValue:
org.opensaml.saml.saml2.core.Response samlResponse = responseBuilder.buildObject();
// Compute and add SignatureValue element to Signature
XMLObjectProviderRegistrySupport.getMarshallerFactory()
.getMarshaller(samlResponse).marshall(samlResponse);
Signer.signObject(signature);
I'm using spring-ws (2.1.4) WebServiceTemplate with a custom WebServiceMessageCallback to insert the security header with a SAML which I will receive as a org.w3c.dom.Element and only create myself for testing.
I use webServiceTemplate.marshalSendAndReceive(request, new HeaderCallback(ctx, uri)) to marshal and send my request.
My issue is that the verification of the signature fails on the server side, the digests don't match. Comparing the output of the SAML before sending and after receiving I see that on the receiving side I have namespace declarations on elements that didn't have one before sending.
What I currently do in my callback:
#Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
super.doWithMessage(message);
Assert.isInstanceOf(SoapMessage.class, message);
SoapMessage soapMessage = (SoapMessage) message;
SoapHeaderElement securityHeader = soapMessage.getSoapHeader().addHeaderElement(WS_SECURITY_NAME);
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.transform(new DOMSource(assertion), securityHeader.getResult());
} catch (org.springframework.oxm.MarshallingException ex) {
throw new IOException(ex);
}
Does anyone know how I can insert an element into a SOAP XML making sure that the element will not be modified? Or is there a different approach to achieve this using Spring WebServiceTemplate?
I came across org.apache.ws.security.saml.ext.SAMLCallback which has a method setAssertionElement, however I did not find out how to get this working with the WebServiceTemplate (respectively Wss4jSecurityInterceptor) particularly considering that I need to pass in an existing SAML assertion as a parameter.
SAML XML before sending:
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" IssueInstant="2015-09-23T09:46:14.357Z" Version="2.0">
<saml2:Issuer>iTEST</saml2:Issuer>
<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#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>rVbvzGr4LI/Kd0c+kuhqkupSY44=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>TIbtFHnqURfko94eqANDX8UEhw0HSI3xL0sAQ5GbhjVn2DicckzxpoJL3RVPF6KhLOkUPm5IgnF5At6Es69D48DLE+QvWvP0F7VmcdNJHRSnzIWYaJsXfNfDt2AXXM1kanp5Gq8nj1EsT6C8SlkO1x77C3vKkn1nLSNszEkukuhEzA8V7G+l6L65bIveA36IyYqjiVDKIMOIzHMF9qK03Um7qJHWoxvxSig1UPBINlBtDqyhbGW01OnoHP8qXK7bzuP6p3zbBDhhEYMyNV2P8GT8zX1+cv+JE6ghde4K9hyf6V+x6L218L1AOjACEJUkBrxw0q1uJAVGA1UNJPJbJQ==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIC1TCCAb2gAwIBAgIENFWkEzANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBpVEVTVDpjb21tdW5pdHlBMB4XDTE1MDkxMDE0NDcyMFoXDTI1MDkwNzE0NDcyMFowGzEZMBcGA1UEAxMQaVRFU1Q6Y29tbXVuaXR5QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMX9f6af8s8bqZSlSl7nZVmVz9sQuaxK/fYHwKcBCmeQGfx67K6Lrmg4ZkVlMxFPFAZta8i0UHVbFXD6hY4nD8skA+P1RjnHvk4KboBM2krtx7tSC8IzXmtb8sxXsfLKfu1Blqq0lX0kjPyvCIo4FLOSRE//AuKy8zeTSrKAX8tcZYo23mX8TWkp22Hd6O/x4IxuakWRB6fq8DxYWFsu9f1cnt2n3R+d/myrZ6XRVdpZhptWlZjzy90L2VOuHFC3kY8DvgSCdI3UgL+PzD7R3cKUytHlz04LO5cJue4kRaGbNOdgJoRdj4D24BsjpIZ9PCbzSw689N/hRftsUtO5PRECAwEAAaMhMB8wHQYDVR0OBBYEFBL153jJBGRArnJ5dSyHZGKC3vGcMA0GCSqGSIb3DQEBCwUAA4IBAQCWa0KtdISsQecjA3i4Kyr50oynOnas6YK9Jgb3LzJEU911JW4vX4rHmXEe64OkbIO/fpdCE30saTiBoLEFxrUx0xn+0wGvPMIBJZYncaZUUN9412XPEjYoj5DnFjFvdYqNsdNZ9cOs3sa5hRWufea+QFhSJKSG0nouwW1/5WT3/GYtKJZystL2N2q6pUqhwfP5x1JDELTcoiZZzbTkHOxFiz5iLMrZyDL8Bmb856pF7SzmD6NzLXpqiOwMjTeDWyJ3I9mZqDwoTwxC/e8wG42d486GKu3O/BbDkxEv5UDClMY2722oZKKhu3TdQLOIOLJChKgghjuEWOXb+mDdj/Qq</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject>
<saml2:NameID>authSigner</saml2:NameID>
</saml2:Subject>
</saml2:Assertion>
SAML XML after receiving:
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" IssueInstant="2015-09-23T09:46:14.357Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">iTEST</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:Reference URI="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
<ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">rVbvzGr4LI/Kd0c+kuhqkupSY44=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">TIbtFHnqURfko94eqANDX8UEhw0HSI3xL0sAQ5GbhjVn2DicckzxpoJL3RVPF6KhLOkUPm5IgnF5At6Es69D48DLE+QvWvP0F7VmcdNJHRSnzIWYaJsXfNfDt2AXXM1kanp5Gq8nj1EsT6C8SlkO1x77C3vKkn1nLSNszEkukuhEzA8V7G+l6L65bIveA36IyYqjiVDKIMOIzHMF9qK03Um7qJHWoxvxSig1UPBINlBtDqyhbGW01OnoHP8qXK7bzuP6p3zbBDhhEYMyNV2P8GT8zX1+cv+JE6ghde4K9hyf6V+x6L218L1AOjACEJUkBrxw0q1uJAVGA1UNJPJbJQ==</ds:SignatureValue>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Certificate xmlns:ds="http://www.w3.org/2000/09/xmldsig#">MIIC1TCCAb2gAwIBAgIENFWkEzANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBpVEVTVDpjb21tdW5pdHlBMB4XDTE1MDkxMDE0NDcyMFoXDTI1MDkwNzE0NDcyMFowGzEZMBcGA1UEAxMQaVRFU1Q6Y29tbXVuaXR5QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMX9f6af8s8bqZSlSl7nZVmVz9sQuaxK/fYHwKcBCmeQGfx67K6Lrmg4ZkVlMxFPFAZta8i0UHVbFXD6hY4nD8skA+P1RjnHvk4KboBM2krtx7tSC8IzXmtb8sxXsfLKfu1Blqq0lX0kjPyvCIo4FLOSRE//AuKy8zeTSrKAX8tcZYo23mX8TWkp22Hd6O/x4IxuakWRB6fq8DxYWFsu9f1cnt2n3R+d/myrZ6XRVdpZhptWlZjzy90L2VOuHFC3kY8DvgSCdI3UgL+PzD7R3cKUytHlz04LO5cJue4kRaGbNOdgJoRdj4D24BsjpIZ9PCbzSw689N/hRftsUtO5PRECAwEAAaMhMB8wHQYDVR0OBBYEFBL153jJBGRArnJ5dSyHZGKC3vGcMA0GCSqGSIb3DQEBCwUAA4IBAQCWa0KtdISsQecjA3i4Kyr50oynOnas6YK9Jgb3LzJEU911JW4vX4rHmXEe64OkbIO/fpdCE30saTiBoLEFxrUx0xn+0wGvPMIBJZYncaZUUN9412XPEjYoj5DnFjFvdYqNsdNZ9cOs3sa5hRWufea+QFhSJKSG0nouwW1/5WT3/GYtKJZystL2N2q6pUqhwfP5x1JDELTcoiZZzbTkHOxFiz5iLMrZyDL8Bmb856pF7SzmD6NzLXpqiOwMjTeDWyJ3I9mZqDwoTwxC/e8wG42d486GKu3O/BbDkxEv5UDClMY2722oZKKhu3TdQLOIOLJChKgghjuEWOXb+mDdj/Qq</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:NameID xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">authSigner</saml2:NameID>
</saml2:Subject>
</saml2:Assertion>
</wsse:Security>
EDIT: I found a way that does not add the additional namespaces. What I'm doing now is using the javax.xml.soap.SOAPMessage and importing the node:
#Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
super.doWithMessage(message);
Assert.isInstanceOf(SaajSoapMessage.class, message);
try {
SOAPMessage soapMessage = ((SaajSoapMessage) message).getSaajMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
if (soapEnvelope.getHeader() == null) {
soapEnvelope.addHeader();
}
SOAPHeaderElement securityElement = soapEnvelope.getHeader().addHeaderElement(WS_SECURITY_NAME);
securityElement.appendChild(soapPart.importNode(assertion, true));
} catch (SOAPException ex) {
throw new IOException(ex);
}
}
However, even though the diff shows no difference between the outputs the verification is still failing. At this point I'm not sure if I can trust the output and that doing it like that really did not change the SAML...
Any ideas what else could cause the digests not to match?
The following approach (which I already documented on my question as an edit) prevented additional namespaces from being added.
#Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
super.doWithMessage(message);
Assert.isInstanceOf(SaajSoapMessage.class, message);
try {
SOAPMessage soapMessage = ((SaajSoapMessage) message).getSaajMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
if (soapEnvelope.getHeader() == null) {
soapEnvelope.addHeader();
}
SOAPHeaderElement securityElement = soapEnvelope.getHeader().addHeaderElement(WS_SECURITY_NAME);
securityElement.appendChild(soapPart.importNode(assertion, true));
} catch (SOAPException ex) {
throw new IOException(ex);
}
}
I also got the SAML validation to work. It had nothing to do with the way the SAML was added to the SOAP message (also my original approach using Transformer- even though it adds the additional namespaces - validates now). Missing was the ID on the assertion.
Here's how my SAML looks now:
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_63ecd7ce7163507e56270edcd644494b" IssueInstant="2015-09-24T18:23:15.118Z" Version="2.0">
<saml2:Issuer>iTEST</saml2:Issuer>
<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#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#_63ecd7ce7163507e56270edcd644494b">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>yjlkSOIJC3qNYzEYfipGIwoAD9A=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>fIEp5aYFVesexZWAfMM+e8kcwe52nl54xMr92wtz2BZ3TIVkY6u5vfh8hA0q6hkzEEaHV5vM0cEXholekn4og41jhMn7XwmScggrbr/neYBMdE95GRz6Nv2Sc6PzqPTYeFp+Dylho7sy1yZtWAb3jiGm8zdHJIQuk6NNUZhnMPkZqjXpM68U9cRGojAmnczbRVl2couxDp5fErivKJgJuffN3FVBfCFrFOjGpVf00ukZxqJJ3RP+n7wXWl251W0i0KvWCZPCD5gzl69EzNFc78o8khzd26aLIeDFLBQr0BPnrC454dZZ/SSNeH52HtDstNJ6SBrWFAA8c8vnLSJ0fg==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIC1TCCAb2gAwIBAgIENFWkEzANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDExBpVEVTVDpjb21tdW5pdHlBMB4XDTE1MDkxMDE0NDcyMFoXDTI1MDkwNzE0NDcyMFowGzEZMBcGA1UEAxMQaVRFU1Q6Y29tbXVuaXR5QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMX9f6af8s8bqZSlSl7nZVmVz9sQuaxK/fYHwKcBCmeQGfx67K6Lrmg4ZkVlMxFPFAZta8i0UHVbFXD6hY4nD8skA+P1RjnHvk4KboBM2krtx7tSC8IzXmtb8sxXsfLKfu1Blqq0lX0kjPyvCIo4FLOSRE//AuKy8zeTSrKAX8tcZYo23mX8TWkp22Hd6O/x4IxuakWRB6fq8DxYWFsu9f1cnt2n3R+d/myrZ6XRVdpZhptWlZjzy90L2VOuHFC3kY8DvgSCdI3UgL+PzD7R3cKUytHlz04LO5cJue4kRaGbNOdgJoRdj4D24BsjpIZ9PCbzSw689N/hRftsUtO5PRECAwEAAaMhMB8wHQYDVR0OBBYEFBL153jJBGRArnJ5dSyHZGKC3vGcMA0GCSqGSIb3DQEBCwUAA4IBAQCWa0KtdISsQecjA3i4Kyr50oynOnas6YK9Jgb3LzJEU911JW4vX4rHmXEe64OkbIO/fpdCE30saTiBoLEFxrUx0xn+0wGvPMIBJZYncaZUUN9412XPEjYoj5DnFjFvdYqNsdNZ9cOs3sa5hRWufea+QFhSJKSG0nouwW1/5WT3/GYtKJZystL2N2q6pUqhwfP5x1JDELTcoiZZzbTkHOxFiz5iLMrZyDL8Bmb856pF7SzmD6NzLXpqiOwMjTeDWyJ3I9mZqDwoTwxC/e8wG42d486GKu3O/BbDkxEv5UDClMY2722oZKKhu3TdQLOIOLJChKgghjuEWOXb+mDdj/Qq</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject>
<saml2:NameID>authSigner</saml2:NameID>
</saml2:Subject>
</saml2:Assertion>
I'm connecting to a webservice with axis/rampart and was told to remove the InclusiveNamespaces as the prefixList was "" which is not allowed. How do I do that?
The part looks like
<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="wsa soapenv" />
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<ds:Reference URI="#Id-289005241">
<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="" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>bla bla bla=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
Is it possible to configure axis/rampart to not print the inclusivenamespace when it's empty?
I'm using axis/rampart 1.6.2 and connecting to a .NET service
Any ideas how to archive this? Or how do I make it render a non empty prefixList ?
You have to add a custom handler to filter the unwanted xml tag.
custom handler:
package com.perre;
public class InclusiveNamespacesFilter extends AbstractHandler {
public InvocationResponse invoke(MessageContext ctx) throws AxisFault {
SOAPEnvelope msgEnvelope = ctx.getEnvelope();
SOAPHeader msgHeader = msgEnvelope.getHeader();
Iterator theDescendants = msgHeader.getDescendants(true);
while(theDescendants.hasNext()){
Object o = theDescendants.next();
//here, add your code to traverse DOM and get the node to filter
//...
Node aNode = ele.getElementsByTagName("ec:InclusiveNamespacesFilter").item(0);
if(aNode != null){
ele.removeChild(aNode);
}
}
return InvocationResponse.CONTINUE;
}
edit your axis2.xml and declare the handler:
<phase name="PostSecurity">
<handler name="FilterHandler" class="com.perre.InclusiveNamespacesFilter"/>
</phase>
You should be ready to go. Find more reading about custom handlers here.