Ok, I've done some more investigation and realized that my question is really a
bit deeper than what I originally thought. I apologize in advance for the
lengthy post. In this large, legacy CXF 2.3 / WSS4J 1.5 based code that I have,
the intent is to add a SAML Assertion to a message as a signed supporting
token. The way this worked previously is that the code would dynamically change
the signature parts from the spring configuration:
from: {Element}{...}Body; STRTransform; {Element}{...}Timestamp;
{Element}{...}Action; {Element}{...}To; {Element}{...}MessageID;
{Element}{...}ReplyTo
To: {Element}{...}Body; Token; {Element}{...}Timestamp; {Element}{...}Action;
{Element}{...}To; {Element}{...}MessageID; {Element}{...}ReplyTo; Assertion
The addReferencesToSign() would then later scan for Assertion, and add the
appropriate references, like so:
public void addReferencesToSign(@SuppressWarnings("rawtypes") Vector
references, WSSecHeader secHeader)
throws WSSecurityException
{
final Vector<Object> unalteredReferences = new Vector<Object>();
try {
for (int part = 0; part < references.size(); part++) {
final WSEncryptionPart encPart = (WSEncryptionPart)
references.get(part);
final String elemName = encPart.getName();
if (elemName != null && "Assertion".equals(elemName)) {
final Transforms transforms = new Transforms(document);
Element ctx = createSTRParameter(document);
transforms.addTransform(STRTransform.implementedTransformURI, ctx);
sig.addDocument("#" + this.assertionSecRefUri,
transforms, this.getDigestAlgo());
}
else {
unalteredReferences.add(encPart);
}
}
}
super.addReferencesToSign(unalteredReferences, secHeader);
}
Moving on to CXF 2.7 / WSS4J 1.6, I have two problems: Token is no longer a
keyword you can use in signature parts, and transforms & references are added
to signatures in a completely different way. I think I've fixed the latter
problem, with code like this:
public List<javax.xml.crypto.dsig.Reference> addReferencesToSign(
@SuppressWarnings("rawtypes") List<WSEncryptionPart> references,
WSSecHeader secHeader)
throws WSSecurityException
{
List<javax.xml.crypto.dsig.Reference> referenceList = new
ArrayList<javax.xml.crypto.dsig.Reference>();
Transform transform = null;
try {
for (int part = 0; part < references.size(); part++) {
final WSEncryptionPart encPart = (WSEncryptionPart)
references.get(part);
final String elemName = encPart.getName();
if (elemName != null && "Assertion".equals(elemName)) {
Element ctx = createSTRParameter(document);
XMLStructure structure = new DOMStructure(ctx);
transform =
signatureFactory.newTransform(STRTransform.TRANSFORM_URI, structure);
DigestMethod digestMethod =
signatureFactory.newDigestMethod(this.getDigestAlgo(), null);
javax.xml.crypto.dsig.Reference reference =
signatureFactory.newReference("#" + this.assertionSecRefUri,
digestMethod,
Collections.singletonList(transform), null, null);
referenceList.add(reference);
}
}
}
referenceList.addAll( super.addReferencesToSign(references,
secHeader) );
return referenceList;
}
Which may or may not work, but at least doesn't throw anything at the moment.
The removal of Token, on the other hand, is still causing me some trouble. In
general, I've replaced Token with {Element}{...}BinarySecurityToken, and that's
worked and everything is happy. In this case, I get an exception that the
signature can't be done because BinarySecurityToken isn't found:
Caused by: org.apache.ws.security.WSSecurityException: Signature creation
failed (Cannot setup signature data structure)
at
org.apache.ws.security.message.WSSecSignatureBase.addReferencesToSign(WSSecSignatureBase.java:191)
at
org.apache.ws.security.message.WSSecSignature.addReferencesToSign(WSSecSignature.java:411)
at
gov.faa.swim.ssri.wss.wss4j.saml.SupportingSamlTokenSignedAction$WSSecSamlSupportingTokenSignature.addReferencesToSign(SupportingSamlTokenSignedAction.java:268)
at
gov.faa.swim.ssri.wss.wss4j.saml.SupportingSamlTokenSignedAction$WSSecSamlSupportingTokenSignature.build(SupportingSamlTokenSignedAction.java:156)
at
gov.faa.swim.ssri.wss.wss4j.saml.SupportingSamlTokenSignedAction.execute(SupportingSamlTokenSignedAction.java:110)
... 47 more
Caused by: org.apache.ws.security.WSSecurityException: General security error
(WSEncryptBody/WSSignEnvelope: Element to encrypt/sign not found:
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd,
BinarySecurityToken)
at
org.apache.ws.security.message.WSSecSignatureBase.addReferencesToSign(WSSecSignatureBase.java:160)
That leads me to believe that Token was a bit smarter keyword in the past, and
I need to replace it with something smarter in the present to add the SAML
Assertion as a signed supporting token. Which leads me to my questions:
1) How do I modify the Token in signature parts to end up with the SAML
Assertion as a signed supporting token in my SOAP message?
2) Is it necessary in CXF 2.7 / WSS4J 1.6 to customize addReferencesToSign() to
end up with a signed supporting token, or is there an easier / better way to go
about it?
Thanx,
Stephen W. Chappell