3434import java .util .function .Predicate ;
3535import java .util .stream .Collectors ;
3636import javax .xml .crypto .dsig .XMLSignature ;
37- import javax .xml .namespace .QName ;
3837
3938import jakarta .ws .rs .Consumes ;
4039import jakarta .ws .rs .FormParam ;
101100import org .keycloak .saml .SAML2LogoutResponseBuilder ;
102101import org .keycloak .saml .SAMLRequestParser ;
103102import org .keycloak .saml .common .constants .GeneralConstants ;
104- import org .keycloak .saml .common .constants .JBossSAMLConstants ;
105103import org .keycloak .saml .common .constants .JBossSAMLURIConstants ;
106104import org .keycloak .saml .common .exceptions .ConfigurationException ;
107105import org .keycloak .saml .common .exceptions .ProcessingException ;
108- import org .keycloak .saml .common .util .DocumentUtil ;
109106import org .keycloak .saml .processing .core .saml .v2 .common .SAMLDocumentHolder ;
110107import org .keycloak .saml .processing .core .saml .v2 .constants .X500SAMLProfileConstants ;
111108import org .keycloak .saml .processing .core .saml .v2 .util .ArtifactResponseUtil ;
@@ -258,6 +255,7 @@ protected Response basicChecks(String samlRequest, String samlResponse, String s
258255
259256 protected abstract String getBindingType ();
260257 protected abstract boolean containsUnencryptedSignature (SAMLDocumentHolder documentHolder );
258+ protected abstract boolean isMessageFullySigned (SAMLDocumentHolder documentHolder );
261259 protected abstract void verifySignature (String key , SAMLDocumentHolder documentHolder ) throws VerificationException ;
262260 protected abstract SAMLDocumentHolder extractRequestDocument (String samlRequest );
263261 protected abstract SAMLDocumentHolder extractResponseDocument (String response );
@@ -578,7 +576,7 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h
578576 } else {
579577 /* We verify the assertion using original document to handle cases where the IdP
580578 includes whitespace and/or newlines inside tags. */
581- assertionElement = DocumentUtil . getElement (holder . getSamlDocument (), new QName ( JBossSAMLConstants . ASSERTION . get ()) );
579+ assertionElement = AssertionUtil . getAssertionElement (holder );
582580 }
583581
584582 // Validate the response Issuer
@@ -604,7 +602,7 @@ protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder h
604602 boolean signed = AssertionUtil .isSignedElement (assertionElement );
605603 final boolean assertionSignatureNotExistsWhenRequired = config .isWantAssertionsSigned () && !signed ;
606604 final boolean signatureNotValid = signed && config .isValidateSignature () && !AssertionUtil .isSignatureValid (assertionElement , getIDPKeyLocator ());
607- final boolean hasNoSignatureWhenRequired = ! signed && config .isValidateSignature () && ! containsUnencryptedSignature (holder );
605+ final boolean hasNoSignatureWhenRequired = !signed && config .isValidateSignature () && !isMessageFullySigned (holder );
608606
609607 if (assertionSignatureNotExistsWhenRequired || signatureNotValid || hasNoSignatureWhenRequired ) {
610608 logger .error ("validation failed" );
@@ -840,6 +838,11 @@ protected boolean containsUnencryptedSignature(SAMLDocumentHolder documentHolder
840838 return (nl != null && nl .getLength () > 0 );
841839 }
842840
841+ @ Override
842+ protected boolean isMessageFullySigned (SAMLDocumentHolder documentHolder ) {
843+ return AssertionUtil .isSignedElement (documentHolder .getSamlDocument ().getDocumentElement ());
844+ }
845+
843846 @ Override
844847 protected void verifySignature (String key , SAMLDocumentHolder documentHolder ) throws VerificationException {
845848 if ((! containsUnencryptedSignature (documentHolder )) && (documentHolder .getSamlObject () instanceof ResponseType )) {
@@ -879,14 +882,17 @@ protected boolean containsUnencryptedSignature(SAMLDocumentHolder documentHolder
879882 return algorithm != null && signature != null ;
880883 }
881884
885+ @ Override
886+ protected boolean isMessageFullySigned (SAMLDocumentHolder documentHolder ) {
887+ return containsUnencryptedSignature (documentHolder );
888+ }
889+
882890 @ Override
883891 protected void verifySignature (String key , SAMLDocumentHolder documentHolder ) throws VerificationException {
884892 KeyLocator locator = getIDPKeyLocator ();
885893 SamlProtocolUtils .verifyRedirectSignature (documentHolder , locator , session .getContext ().getUri (), key );
886894 }
887895
888-
889-
890896 @ Override
891897 protected SAMLDocumentHolder extractRequestDocument (String samlRequest ) {
892898 return SAMLRequestParser .parseRequestRedirectBinding (samlRequest , maxInflatingSize );
@@ -906,20 +912,31 @@ protected String getBindingType() {
906912
907913 protected class ArtifactBinding extends Binding {
908914
909- private boolean unencryptedSignaturesVerified = false ;
915+ // artifact binding is processed twice, first with the art and then with the response, vars to store the first pass
916+ private Boolean containsUnencryptedSignature = null ;
917+ private Boolean messageFullySigned = null ;
918+ private Boolean verified = null ;
910919
911920 @ Override
912921 protected boolean containsUnencryptedSignature (SAMLDocumentHolder documentHolder ) {
913- if (unencryptedSignaturesVerified ) {
914- return true ;
922+ if (containsUnencryptedSignature != null ) {
923+ return containsUnencryptedSignature ;
915924 }
916925 NodeList nl = documentHolder .getSamlDocument ().getElementsByTagNameNS (XMLSignature .XMLNS , "Signature" );
917- return (nl != null && nl .getLength () > 0 );
926+ containsUnencryptedSignature = (nl != null && nl .getLength () > 0 );
927+ messageFullySigned = AssertionUtil .isSignedElement (documentHolder .getSamlDocument ().getDocumentElement ());
928+ return containsUnencryptedSignature ;
929+ }
930+
931+ @ Override
932+ protected boolean isMessageFullySigned (SAMLDocumentHolder documentHolder ) {
933+ containsUnencryptedSignature (documentHolder );
934+ return messageFullySigned ;
918935 }
919936
920937 @ Override
921938 protected void verifySignature (String key , SAMLDocumentHolder documentHolder ) throws VerificationException {
922- if (unencryptedSignaturesVerified ) {
939+ if (verified != null ) {
923940 // this is the second pass and signatures were already verified in the artifact response time
924941 return ;
925942 }
@@ -938,13 +955,14 @@ protected void verifySignature(String key, SAMLDocumentHolder documentHolder) th
938955 }
939956 }
940957 SamlProtocolUtils .verifyDocumentSignature (documentHolder .getSamlDocument (), getIDPKeyLocator ());
941- unencryptedSignaturesVerified = true ; // mark signatures as verified
958+ verified = true ;
942959 }
943960
944961 @ Override
945962 protected SAMLDocumentHolder extractRequestDocument (String samlRequest ) {
946963 throw new UnsupportedOperationException ("SAML request is not compliant with Artifact binding" );
947964 }
965+
948966 @ Override
949967 protected SAMLDocumentHolder extractResponseDocument (String response ) {
950968 byte [] samlBytes = PostBindingUtil .base64Decode (response );
0 commit comments