This is an automated email from the ASF dual-hosted git repository. coheigea pushed a commit to branch coheigea/saml-refactor-new in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
The following commit(s) were added to refs/heads/coheigea/saml-refactor-new by this push: new dee35484d First refactor of SAML KeyInfo processing dee35484d is described below commit dee35484d6fa7a0c19ae6f8d3ffa1606cd02793d Author: Colm O hEigeartaigh <cohei...@apache.org> AuthorDate: Wed Jun 25 10:45:18 2025 +0100 First refactor of SAML KeyInfo processing --- .../org/apache/wss4j/common/saml/SAMLKeyInfo.java | 0 .../wss4j/dom/processor/SAMLTokenProcessor.java | 6 +++--- .../wss4j/dom/saml/WSSSAMLKeyInfoProcessor.java | 13 ++++++++----- .../org/apache/wss4j/dom/saml/WSSecSignatureSAML.java | 8 +++----- .../apache/wss4j/dom/str/EncryptedKeySTRParser.java | 2 +- .../wss4j/dom/str/SecurityTokenRefSTRParser.java | 2 +- .../org/apache/wss4j/dom/str/SignatureSTRParser.java | 4 ++-- .../wss4j/common/saml/SAMLKeyInfoProcessor.java | 7 ++++++- .../java/org/apache/wss4j/common/saml/SAMLUtil.java | 19 ++++++++++++++----- .../wss4j/common/saml/SamlAssertionWrapper.java | 10 ++++++---- .../impl/securityToken/SamlSecurityTokenImpl.java | 2 +- 11 files changed, 45 insertions(+), 28 deletions(-) diff --git a/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLKeyInfo.java b/ws-security-common/src/main/java/org/apache/wss4j/common/saml/SAMLKeyInfo.java similarity index 100% rename from ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLKeyInfo.java rename to ws-security-common/src/main/java/org/apache/wss4j/common/saml/SAMLKeyInfo.java diff --git a/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java b/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java index ff5573aab..43cfbcfe1 100644 --- a/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java +++ b/ws-security-dom/src/main/java/org/apache/wss4j/dom/processor/SAMLTokenProcessor.java @@ -154,7 +154,7 @@ public class SAMLTokenProcessor implements Processor { // Save subject certs and secrets for further processing SAMLKeyInfo keyInfo = - SAMLUtil.getCredentialFromSubject(samlAssertion, new WSSSAMLKeyInfoProcessor(data), + SAMLUtil.getCredentialFromSubject(samlAssertion, new WSSSAMLKeyInfoProcessor(), data, data.getSigVerCrypto()); if (keyInfo != null) { if (keyInfo.getPublicKey() != null) { @@ -179,7 +179,7 @@ public class SAMLTokenProcessor implements Processor { ) throws WSSecurityException { // Parse the subject if it exists samlAssertion.parseSubject( - new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto() + new WSSSAMLKeyInfoProcessor(), data, data.getSigVerCrypto() ); // Now delegate the rest of the verification to the Validator @@ -206,7 +206,7 @@ public class SAMLTokenProcessor implements Processor { } SAMLKeyInfo samlKeyInfo = SAMLUtil.getCredentialFromKeyInfo( - keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto() + keyInfo.getDOM(), new WSSSAMLKeyInfoProcessor(), data, data.getSigVerCrypto() ); PublicKey key = null; diff --git a/ws-security-dom/src/main/java/org/apache/wss4j/dom/saml/WSSSAMLKeyInfoProcessor.java b/ws-security-dom/src/main/java/org/apache/wss4j/dom/saml/WSSSAMLKeyInfoProcessor.java index 3d6e8e8c2..23834daa4 100644 --- a/ws-security-dom/src/main/java/org/apache/wss4j/dom/saml/WSSSAMLKeyInfoProcessor.java +++ b/ws-security-dom/src/main/java/org/apache/wss4j/dom/saml/WSSSAMLKeyInfoProcessor.java @@ -29,10 +29,13 @@ import org.w3c.dom.Node; import org.w3c.dom.Text; import org.apache.wss4j.common.crypto.AlgorithmSuite; import org.apache.wss4j.common.crypto.AlgorithmSuiteValidator; +import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.principal.WSDerivedKeyTokenPrincipal; import org.apache.wss4j.common.saml.SAMLKeyInfo; import org.apache.wss4j.common.saml.SAMLKeyInfoProcessor; +import org.apache.wss4j.common.saml.SAMLUtil; +import org.apache.wss4j.common.saml.SamlAssertionWrapper; import org.apache.wss4j.common.token.SecurityTokenReference; import org.apache.wss4j.common.dom.WSConstants; import org.apache.wss4j.common.dom.engine.WSSecurityEngineResult; @@ -58,13 +61,13 @@ public class WSSSAMLKeyInfoProcessor implements SAMLKeyInfoProcessor { private static final QName BINARY_SECRET_05_12 = new QName(WST_NS_05_12, "BinarySecret"); - private RequestData data; - - public WSSSAMLKeyInfoProcessor(RequestData data) { - this.data = data; + public SAMLKeyInfo processSAMLKeyInfoFromAssertionElement(Element assertionElement, RequestData data, + Crypto userCrypto) throws WSSecurityException { + SamlAssertionWrapper assertion = new SamlAssertionWrapper(assertionElement); + return SAMLUtil.getCredentialFromSubject(assertion, this, data, userCrypto); } - public SAMLKeyInfo processSAMLKeyInfo(Element keyInfoElement) throws WSSecurityException { + public SAMLKeyInfo processSAMLKeyInfo(Element keyInfoElement, RequestData data) throws WSSecurityException { // // First try to find an EncryptedKey, BinarySecret or a SecurityTokenReference via DOM // diff --git a/ws-security-dom/src/main/java/org/apache/wss4j/dom/saml/WSSecSignatureSAML.java b/ws-security-dom/src/main/java/org/apache/wss4j/dom/saml/WSSecSignatureSAML.java index d6373fc12..a7cf3051a 100644 --- a/ws-security-dom/src/main/java/org/apache/wss4j/dom/saml/WSSecSignatureSAML.java +++ b/ws-security-dom/src/main/java/org/apache/wss4j/dom/saml/WSSecSignatureSAML.java @@ -37,7 +37,7 @@ import org.apache.wss4j.common.crypto.CryptoType; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.saml.OpenSAMLUtil; import org.apache.wss4j.common.saml.SAMLKeyInfo; -import org.apache.wss4j.common.saml.SAMLUtil; +import org.apache.wss4j.common.saml.SAMLKeyInfoProcessor; import org.apache.wss4j.common.saml.SamlAssertionWrapper; import org.apache.wss4j.common.token.BinarySecurity; import org.apache.wss4j.common.token.DOMX509Data; @@ -243,10 +243,8 @@ public class WSSecSignatureSAML extends WSSecSignature { SignatureActionToken actionToken = new SignatureActionToken(); data.setSignatureToken(actionToken); actionToken.setCrypto(userCrypto); - SAMLKeyInfo samlKeyInfo = - SAMLUtil.getCredentialFromSubject( - samlAssertion, new WSSSAMLKeyInfoProcessor(data), userCrypto - ); + SAMLKeyInfoProcessor keyInfoProcessor = new WSSSAMLKeyInfoProcessor(); + SAMLKeyInfo samlKeyInfo = keyInfoProcessor.processSAMLKeyInfoFromAssertionElement(samlToken, data, userCrypto); if (samlKeyInfo != null) { publicKey = samlKeyInfo.getPublicKey(); certs = samlKeyInfo.getCerts(); diff --git a/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/EncryptedKeySTRParser.java b/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/EncryptedKeySTRParser.java index ed2a0f55b..61c157865 100644 --- a/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/EncryptedKeySTRParser.java +++ b/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/EncryptedKeySTRParser.java @@ -150,7 +150,7 @@ public class EncryptedKeySTRParser implements STRParser { SAMLKeyInfo samlKi = SAMLUtil.getCredentialFromSubject(samlAssertion, - new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto()); + new WSSSAMLKeyInfoProcessor(), data, data.getSigVerCrypto()); parserResult.setCerts(samlKi.getCerts()); parserResult.setPublicKey(samlKi.getPublicKey()); } else { diff --git a/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/SecurityTokenRefSTRParser.java b/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/SecurityTokenRefSTRParser.java index 3e952147a..f9f1039ef 100644 --- a/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/SecurityTokenRefSTRParser.java +++ b/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/SecurityTokenRefSTRParser.java @@ -96,7 +96,7 @@ public class SecurityTokenRefSTRParser implements STRParser { ) throws WSSecurityException { STRParserUtil.checkSamlTokenBSPCompliance(secRef, samlAssertion.getSaml2() != null, data.getBSPEnforcer()); SAMLKeyInfo samlKi = - SAMLUtil.getCredentialFromSubject(samlAssertion, new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto()); + SAMLUtil.getCredentialFromSubject(samlAssertion, new WSSSAMLKeyInfoProcessor(), data, data.getSigVerCrypto()); if (samlKi == null) { throw new WSSecurityException( WSSecurityException.ErrorCode.FAILED_CHECK, "invalidSAMLToken", diff --git a/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/SignatureSTRParser.java b/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/SignatureSTRParser.java index cd23bd3d5..011456211 100644 --- a/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/SignatureSTRParser.java +++ b/ws-security-dom/src/main/java/org/apache/wss4j/dom/str/SignatureSTRParser.java @@ -139,7 +139,7 @@ public class SignatureSTRParser implements STRParser { SAMLKeyInfo samlKi = SAMLUtil.getCredentialFromSubject(samlAssertion, - new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto()); + new WSSSAMLKeyInfoProcessor(), data, data.getSigVerCrypto()); X509Certificate[] foundCerts = samlKi.getCerts(); if (foundCerts != null && foundCerts.length > 0) { parserResult.setCerts(new X509Certificate[]{foundCerts[0]}); @@ -383,7 +383,7 @@ public class SignatureSTRParser implements STRParser { } else { samlAssertion = new SamlAssertionWrapper(processedToken); samlAssertion.parseSubject( - new WSSSAMLKeyInfoProcessor(data), data.getSigVerCrypto() + new WSSSAMLKeyInfoProcessor(), data, data.getSigVerCrypto() ); } STRParserUtil.checkSamlTokenBSPCompliance(secRef, samlAssertion.getSaml2() != null, data.getBSPEnforcer()); diff --git a/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLKeyInfoProcessor.java b/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLKeyInfoProcessor.java index d2f1cc4bc..4f9097f18 100644 --- a/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLKeyInfoProcessor.java +++ b/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLKeyInfoProcessor.java @@ -19,6 +19,8 @@ package org.apache.wss4j.common.saml; +import org.apache.wss4j.common.crypto.Crypto; +import org.apache.wss4j.common.dom.RequestData; import org.apache.wss4j.common.ext.WSSecurityException; import org.w3c.dom.Element; @@ -27,5 +29,8 @@ import org.w3c.dom.Element; */ public interface SAMLKeyInfoProcessor { - SAMLKeyInfo processSAMLKeyInfo(Element keyInfoElement) throws WSSecurityException; + SAMLKeyInfo processSAMLKeyInfoFromAssertionElement(Element samlAssertion, RequestData data, + Crypto userCrypto) throws WSSecurityException; + + SAMLKeyInfo processSAMLKeyInfo(Element keyInfoElement, RequestData data) throws WSSecurityException; } diff --git a/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLUtil.java b/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLUtil.java index 09a681550..698c70e6b 100644 --- a/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLUtil.java +++ b/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SAMLUtil.java @@ -36,6 +36,7 @@ import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.crypto.CryptoType; +import org.apache.wss4j.common.dom.RequestData; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.util.XMLUtils; import org.opensaml.saml.saml2.core.SubjectConfirmationData; @@ -70,21 +71,23 @@ public final class SAMLUtil { * * @param samlAssertion The SAML Assertion * @param keyInfoProcessor A pluggable way to parse the KeyInfo + * @param data RequestData * @return a SAMLKeyInfo object * @throws WSSecurityException */ public static SAMLKeyInfo getCredentialFromSubject( SamlAssertionWrapper samlAssertion, SAMLKeyInfoProcessor keyInfoProcessor, + RequestData data, Crypto sigCrypto ) throws WSSecurityException { if (samlAssertion.getSaml1() != null) { return getCredentialFromSubject( - samlAssertion.getSaml1(), keyInfoProcessor, sigCrypto + samlAssertion.getSaml1(), keyInfoProcessor, data, sigCrypto ); } else if (samlAssertion.getSaml2() != null) { return getCredentialFromSubject( - samlAssertion.getSaml2(), keyInfoProcessor, sigCrypto + samlAssertion.getSaml2(), keyInfoProcessor, data, sigCrypto ); } @@ -97,6 +100,7 @@ public final class SAMLUtil { * SAML 1.1 assertion * @param assertion The SAML 1.1 assertion * @param keyInfoProcessor A pluggable way to parse the KeyInfo + * @param data RequestData * @param sigCrypto A Crypto instance * @return The SAMLKeyInfo object obtained from the Subject * @throws WSSecurityException @@ -104,6 +108,7 @@ public final class SAMLUtil { public static SAMLKeyInfo getCredentialFromSubject( org.opensaml.saml.saml1.core.Assertion assertion, SAMLKeyInfoProcessor keyInfoProcessor, + RequestData data, Crypto sigCrypto ) throws WSSecurityException { for (org.opensaml.saml.saml1.core.Statement stmt : assertion.getStatements()) { @@ -128,7 +133,7 @@ public final class SAMLUtil { XMLUtils.getDirectChildElement(sub, "KeyInfo", SIG_NS); if (keyInfoElement != null) { return getCredentialFromKeyInfo( - keyInfoElement, keyInfoProcessor, sigCrypto + keyInfoElement, keyInfoProcessor, data, sigCrypto ); } } @@ -142,6 +147,7 @@ public final class SAMLUtil { * SAML 2 assertion * @param assertion The SAML 2 assertion * @param keyInfoProcessor A pluggable way to parse the KeyInfo + * @param data RequestData * @param sigCrypto A Crypto instance * @return The SAMLKeyInfo object obtained from the Subject * @throws WSSecurityException @@ -149,6 +155,7 @@ public final class SAMLUtil { public static SAMLKeyInfo getCredentialFromSubject( org.opensaml.saml.saml2.core.Assertion assertion, SAMLKeyInfoProcessor keyInfoProcessor, + RequestData data, Crypto sigCrypto ) throws WSSecurityException { org.opensaml.saml.saml2.core.Subject samlSubject = assertion.getSubject(); @@ -164,7 +171,7 @@ public final class SAMLUtil { XMLUtils.getDirectChildElement(sub, "KeyInfo", SIG_NS); if (keyInfoElement != null) { return getCredentialFromKeyInfo( - keyInfoElement, keyInfoProcessor, sigCrypto + keyInfoElement, keyInfoProcessor, data, sigCrypto ); } } @@ -179,6 +186,7 @@ public final class SAMLUtil { * KeyInfo (DOM Element) argument. * @param keyInfoElement The KeyInfo as a DOM Element * @param keyInfoProcessor A pluggable way to parse the KeyInfo + * @param data The RequestData object * @param sigCrypto A Crypto instance * @return The credential (as a SAMLKeyInfo object) * @throws WSSecurityException @@ -186,13 +194,14 @@ public final class SAMLUtil { public static SAMLKeyInfo getCredentialFromKeyInfo( Element keyInfoElement, SAMLKeyInfoProcessor keyInfoProcessor, + RequestData data, Crypto sigCrypto ) throws WSSecurityException { // // First try to find an EncryptedKey, BinarySecret or a SecurityTokenReference via DOM // if (keyInfoProcessor != null) { - SAMLKeyInfo samlKeyInfo = keyInfoProcessor.processSAMLKeyInfo(keyInfoElement); + SAMLKeyInfo samlKeyInfo = keyInfoProcessor.processSAMLKeyInfo(keyInfoElement, data); if (samlKeyInfo != null) { return samlKeyInfo; } diff --git a/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SamlAssertionWrapper.java b/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SamlAssertionWrapper.java index 29e9b3277..62ad1a25f 100644 --- a/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SamlAssertionWrapper.java +++ b/ws-security-saml/src/main/java/org/apache/wss4j/common/saml/SamlAssertionWrapper.java @@ -27,6 +27,7 @@ import java.util.List; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.crypto.CryptoType; +import org.apache.wss4j.common.dom.RequestData; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.saml.builder.SAML1ComponentBuilder; import org.apache.wss4j.common.saml.builder.SAML2ComponentBuilder; @@ -581,7 +582,7 @@ public class SamlAssertionWrapper { * @throws WSSecurityException */ public void verifySignature( - SAMLKeyInfoProcessor keyInfoProcessor, Crypto sigCrypto + SAMLKeyInfoProcessor keyInfoProcessor, RequestData data, Crypto sigCrypto ) throws WSSecurityException { Signature sig = getSignature(); if (sig != null) { @@ -593,7 +594,7 @@ public class SamlAssertionWrapper { ); } SAMLKeyInfo samlKeyInfo = - SAMLUtil.getCredentialFromKeyInfo(keyInfo.getDOM(), keyInfoProcessor, sigCrypto); + SAMLUtil.getCredentialFromKeyInfo(keyInfo.getDOM(), keyInfoProcessor, data, sigCrypto); verifySignature(samlKeyInfo); } else { LOG.debug("SamlAssertionWrapper: no signature to validate"); @@ -668,17 +669,18 @@ public class SamlAssertionWrapper { */ public void parseSubject( SAMLKeyInfoProcessor keyInfoProcessor, + RequestData data, Crypto sigCrypto ) throws WSSecurityException { if (samlVersion == SAMLVersion.VERSION_11) { subjectKeyInfo = SAMLUtil.getCredentialFromSubject( - (org.opensaml.saml.saml1.core.Assertion)samlObject, keyInfoProcessor, sigCrypto + (org.opensaml.saml.saml1.core.Assertion)samlObject, keyInfoProcessor, data, sigCrypto ); } else if (samlVersion == SAMLVersion.VERSION_20) { subjectKeyInfo = SAMLUtil.getCredentialFromSubject( - (org.opensaml.saml.saml2.core.Assertion)samlObject, keyInfoProcessor, sigCrypto + (org.opensaml.saml.saml2.core.Assertion)samlObject, keyInfoProcessor, data, sigCrypto ); } } diff --git a/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java b/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java index 33cb4e2ef..65d6c705e 100644 --- a/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java +++ b/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java @@ -93,7 +93,7 @@ public class SamlSecurityTokenImpl extends AbstractInboundSecurityToken implemen this.samlAssertionWrapper = new SamlAssertionWrapper(assertionElem); subjectKeyInfo = - SAMLUtil.getCredentialFromSubject(samlAssertionWrapper, null, + SAMLUtil.getCredentialFromSubject(samlAssertionWrapper, null, null, securityProperties.getSignatureVerificationCrypto()); } else { // Possibly an Encrypted Assertion...we just need the key here