diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java index 89d668052e..714ee3f6f5 100755 --- a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java +++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtil.java @@ -41,7 +41,6 @@ import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.exceptions.fed.IssueInstantMissingException; import org.keycloak.saml.common.util.DocumentUtil; -import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxUtil; import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response; import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature; @@ -560,7 +559,7 @@ public class AssertionUtil { SAMLParser parser = new SAMLParser(); JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement); - AssertionType assertion = (AssertionType) parser.parse(StaxParserUtil.getXMLEventReader(DocumentUtil + AssertionType assertion = (AssertionType) parser.parse(parser.createEventReader(DocumentUtil .getNodeAsStream(decryptedDocumentElement))); responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion)); diff --git a/saml-core/src/test/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParserTest.java b/saml-core/src/test/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParserTest.java index fdacdd7412..52dd7baa9a 100644 --- a/saml-core/src/test/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParserTest.java +++ b/saml-core/src/test/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParserTest.java @@ -16,11 +16,16 @@ */ package org.keycloak.saml.processing.core.parsers.saml; +import org.keycloak.common.util.Base64; +import org.keycloak.common.util.DerUtils; import org.keycloak.dom.saml.v2.assertion.AssertionType; import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType; +import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil; import java.io.InputStream; +import java.security.PrivateKey; + import org.junit.Test; import static org.junit.Assert.*; @@ -35,12 +40,22 @@ import org.w3c.dom.Element; /** * Test class for SAML parser. * + * To create SAML XML for use in the test, use for instance https://www.samltool.com, {@link #PRIVATE_KEY} and + * {@link #PUBLIC_CERT}. + * * TODO: Add further tests. * * @author hmlnarik */ public class SAMLParserTest { + private static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOJDgeiUFOERg6N2qUeLjkE7HDzg4h2m4hMG8WDYLhuAm6k2pq+1SkRDvisD67y2AvXXFz069Vw5TMDnpbmGpigEbdr+YT7As+YpVhxI1nSwTzzEAuL2Ywun1FNfOFAeBt6hzQ/veJ+rc3D3BSgjeY/yiZNen36T3BD8pi3HojErAgMBAAECgYBWmtpVqKCZSXfmkJvYy70GkNaNItLJ4L+14rlvhS+YzVBHo6iHps+nc3qNwnFwCQb3DH5TrIaP50rOp5wSeEyOWk7fOJeAwM4Vsc3d+av/Iu/WwNDyAFW3gGO19YvccfGvEbToMPtppOt47UDK26xfibCwUFwEGg0hGc0gcVQWMQJBAPl8YnETSjI0wZuaSdkUp2/FtHEAZa1yFPtPx7CVCpUG53frKOAx2t0N7AQ2vQUNPqOas8gDGr5O5J+l9tjOD0MCQQDoK+asMuMnSClm/RZRFIckcToFwjfgNQY/AKN31k705jJr+3+er3VlODL7dpnF0X2mVDjiXIp4hH9K0qfW+TP5AkAQOIMaAPwQ+Zcg684jXBFq1freYf06YrF0iYJdO8N9Xv6LsHFu6i7lsnMG7xwpCOxqrLNFrNX/S5fXvW2oOPWLAkEAiTu547tIjaWX42ph0JdDsoTC+Tht8rck9ASam3Evxo5y62UDcHbh+2yWphDaoBVOIgzSeuqcZtRasY2G7AjtcQJAEiXYeHB5+lancDDkBhH8KKdl1+FORRB9kJ4gxTwrjLwprWFjdatMb3O+xJGss+KnVUa/THRa5CRX4pHh93711Q=="; + + /** + * The public certificate that corresponds to {@link #PRIVATE_KEY}. + */ + private static final String PUBLIC_CERT = "MIICXjCCAcegAwIBAgIBADANBgkqhkiG9w0BAQ0FADBLMQswCQYDVQQGEwJubzERMA8GA1UECAwIVmVzdGZvbGQxEzARBgNVBAoMCkV4YW1wbGVPcmcxFDASBgNVBAMMC2V4YW1wbGUub3JnMCAXDTE3MDIyNzEwNTY0MFoYDzIxMTcwMjAzMTA1NjQwWjBLMQswCQYDVQQGEwJubzERMA8GA1UECAwIVmVzdGZvbGQxEzARBgNVBAoMCkV4YW1wbGVPcmcxFDASBgNVBAMMC2V4YW1wbGUub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiQ4HolBThEYOjdqlHi45BOxw84OIdpuITBvFg2C4bgJupNqavtUpEQ74rA+u8tgL11xc9OvVcOUzA56W5hqYoBG3a/mE+wLPmKVYcSNZ0sE88xALi9mMLp9RTXzhQHgbeoc0P73ifq3Nw9wUoI3mP8omTXp9+k9wQ/KYtx6IxKwIDAQABo1AwTjAdBgNVHQ4EFgQUzWjvSL0O2V2B2N9G1qARQiVgv3QwHwYDVR0jBBgwFoAUzWjvSL0O2V2B2N9G1qARQiVgv3QwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQBgvKTTcLGlF0KvnIGxkzdaFeYewQtsQZHgnUt+JGKge0CyUU+QPVFhrH19b7fjKeykq/avm/2hku4mKaPyRYpvU9Gm+ARz67rs/vr0ZgJFk00TGI6ssGhdFd7iCptuIh5lEvWk1hD5LzThOI3isq0gK2tTbhafQOkKa45IwbOQ8Q=="; + private SAMLParser parser; @Before @@ -74,6 +89,28 @@ public class SAMLParserTest { } } + @Test + public void testSaml20EncryptedAssertionWithNewlines() throws Exception { + try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4489-encrypted-assertion-with-newlines.xml")) { + Object parsedObject = parser.parse(st); + assertThat(parsedObject, instanceOf(ResponseType.class)); + + ResponseType resp = (ResponseType) parsedObject; + assertThat(resp.getAssertions().size(), is(1)); + + ResponseType.RTChoiceType rtChoiceType = resp.getAssertions().get(0); + assertNull(rtChoiceType.getAssertion()); + assertNotNull(rtChoiceType.getEncryptedAssertion()); + + PrivateKey privateKey = DerUtils.decodePrivateKey(Base64.decode(PRIVATE_KEY)); + ResponseType rtWithDecryptedAssertion = AssertionUtil.decryptAssertion(resp, privateKey); + + rtChoiceType = rtWithDecryptedAssertion.getAssertions().get(0); + assertNotNull(rtChoiceType.getAssertion()); + assertNull(rtChoiceType.getEncryptedAssertion()); + } + } + @Test public void testSaml20EncryptedAssertionsSignedTwoExtensionsReceivedWithRedirectBinding() throws Exception { Element el; diff --git a/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4489-encrypted-assertion-with-newlines.xml b/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4489-encrypted-assertion-with-newlines.xml new file mode 100644 index 0000000000..3d237a2516 --- /dev/null +++ b/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4489-encrypted-assertion-with-newlines.xml @@ -0,0 +1,32 @@ + + http://idp.example.com/metadata.php + + + + + + + + + + + + + BpU+yCD3m1WdIGDfKnMOplsAzVZd/1cJZwu7l8/Rc/pMXxrYBR4m5WGxyKr+YwJoV3n1+CtYzrsklRN3Ck3Z7seRQf3bluWIvruVSS5k7HpTtZmyY/k0/Y0oTRr8z6YJ8MzL9veyM9EVcwIBFZypPN5ep+HDgz06QV0LAlFkGlQ= + + + + + + + ypy8aPtoV1/PZQsreFUCbqlfFJKPCz5oNtBih/rsk4cQa11+hZelT5w6hJo8eocd/1R1t4O0ctqezqG16md/KVDUh3a6SX2BufreUJ/i1DkZmBDg7CRruDcm69kKIUbFkbFy6d6RI0lk6vijdHttxbDKTUTSDD3yUwSXheVZfzzJoKVvvmNAA1WGCJezF4KS+LEKCtMWft/4IZ/IUmowSTKCTCaAGRLog0ryVBQn79ddpfjvuvW7LAQD4sS1Qfi1YNpkp1s8dz1kf2DHyHk5nrfB2rxNGubx4A+iI65JiyONkaTjLHogd28YvpcXA7knvfoODIy+v1ZbtaL4nnMR7ypQXNMMVrgQcHeGMBwdlaQxgjpXzyFJbfQNhZrTeYm3a4CQBk34ax65NRpDpOxtZ/hp4dgG3r4B2dRwyBWQjUB0WuLj3qsDOlrhHfIWLtkDeCeJ9rs3OPjvrlz1QzEzX0zIHQ8p4Cc9mgEQoptYt/EJ3eLUx9qj9Q7FTm5kWhtSfoVvykJlSJS8lk+Y21CV9q90CK64jupBWyRT2B1kgaap12EgKHKn03OUWiuWif7ceXXwVbKNgqjXiHgWDq6YqN77Lq7FTBbk+Ck1fBVdA+ETOMZy/g8DNp+9YwYVRgpezzdZ7PQjzHZbQaV8YPUu8VrENAJL5QglbMArkxig/MPKxu8WllXDC62CqC4bB5rVNH4tAgItYiP4Mrvb0mRGwIuPr7vpKTRrk7/GX60QN0Ye90JEfbgXAPKwkPsVgWeqztjvCBqkI3nPTTiFtfJPbaFhA0KiHaxoqWF1lzqXWLoIPCDIgWU2CHQbDmlAeRop1Obeuk7vwoI87W/20OnwHWmv3mJ8J46z8XObDaRcnSK/u2XFdalbzcRHGP8d0FnAWoHRoITj79xrmvbcCbZMLfRtWPRc42hvTXPVfPI+Za89ObypMBje+pLGXSSc/N8d3CJ38BBghx+t+skPwy56ISD6xe0FabI/XgV3PQyHu5cWiOCyqZLGxMieRk6mfcswWN+jgaV7lXQ9EN48WGfmlhcBBgKvaLo74Y4EnZvi3nK8BQBoR1AQf9eOoa1DVShqPXyVL5hEHcawEfOeAtK17NpH6jbiy75NVAGFyTgWDLHfyYOVMZXEb4K8EaUnWZS6xnW4EcQKWwhw8Y7zb2v+SMpY2xx1PT+7Q1dSfssLndIg5k9BdgVn3IWdS+oa8DCLt3kIwwgTyENsf1iEgJ9Z0dMOeSbbR3vHm0KquTZGCcSZYjf3bkpg02CcX/Dqf9tTUHlks8ma6aoFhviQUBJ2PCjuKN4UuzNNpKp0SNQraiyKdXHbYBGv8STc5Q2TXc0NuM0P1N7TU66BKNd3YcjUkrZF9IZ8QosRD7WWhKNUh5thDI2fFhqNPcm/BXfT5lMLYZ5DrhG1cCH2HR3pqmnyKiBxEpAqIgAEa3GMuKIJ6h+8rwyB+Ku7xQ/xBpL20CfyyCtsHGns69eWJdb4QxijJtWMgAsB+Pvph6K4eDEfgYid/ORBMpx66LjO1xWx7cra2PsoSpQzc0ZabqJG6Qd8xyFJb8kGyEkXzmju/q164+iDmm8yuVUAr4BJsdtaJHFHgLH0uwRtFSMRn3G7gh2v4kLW35tEhWBJ18x8qrrG6PyQJYrXkaRHLWK2vuHJz0Wg97fgd8FVDUuG1xEHTvRXl9TeMb3rn9L6oe/G7lRKXXvDZqK6KCg7qVArGQWLfooEte5LC9bXR9aWIWEopphRZbd1NcRDbckSqV2vfdiKYY3mfBJ7K76y+n3SOGlx3Cf7/y8EEfF4p2GqcIHxBe2/1K6MKeWaWt/x74G0RuqtYUeryfpzM6aVGHPEuaS/jamwoBHre2/hkalHjAx1u61UIBJXwnfgXr8dgyf/Suyw24mh2xQ9ZvvAuLu5IUCKwCsHyeUYUzoyMUE3VILbpqAvgcfSrhtuPtUEu/3xb7hpoRyTPcLpwKbJ55OmyXoK9XfkOs2cvM9EziB1KHSnrAabJ7geNEHiLFNtDJTyq4F9ZmybAt7SgXDWV5FBqIKYqVBcKNVouh7bdKRhSuJiBsD0t32jSwP+tj1tycCLo2ISz1Bi4R46Wp55hIyx9PBG6H5Gu8xCXvhq4+uh7gSEW9D52aqtYDiYyhCa2bpTFbUPT6nlR4yZcXHqBMoiKjzqrpVltcn96niZYJd90qd4x6Q3VMkja6xNEKluXDUoG3mV1JgvNogodSIPW0de2W59bZt7atFZdKNF4WBzKaETMkYSi6CrvKAuJitMehnbDKwAn03fRe0pqE0nVumrGcYRrppzjkCEptyNIIa8Ct5sHL5ITKfoUGkRjMVoaq57xX98ZTpkF4ablTS2Hjux+AAGyvScabfH8Uqbq2qZ/xOaBpZwi/D7zwWTFzFTBvjUcJTnlrF1SRwfSdUhWyg2fxIXUYsLWgXJVHOfmwhAOduoCLWEbWfgQnYVd9IwTPHm3MK7fw8Ua3zW4mh+Mj8G45OjuG927E5MTHNIBv30GB+o4E9ROkOL0I3+SRXOziRae28zHhmDko0lCO3AzWaTlS/GjtCDhf7J2asQvNBNRIuh/8VOA/cSVYiDo1c4De+pczljz8EIYRIT/5NsbMfDNDMdZebNyARSolCDoYOBMssuxgn1wsXWRYRRZurosrI/038B1SwjDMFwv1E5wKygozrvoko7/wmOOds9W3GIfVxQ7eLw+9hfj5nAP+JXJ4bt3rQ2NBXu5+voAo3efphhmBTtT4y1O/0D9BOFjsIo6YCouMR5bsryGlE6Ioyc6uZ9VFM9uQqN/oeMhKovTWDtKSTgL9XwnG+5zbpBAWUImfb/Md7+6O1nQA7DGyN6+F+gFSv6B8cBkXtWmkkhmGJii/vGcp03mTse/Ky12HGMpfl4sNCcGhSS55I+s/qh3ao9rFoFj7a/GPdvGGlP2KKjogDRRX1SABWTRWGxXnH1JLUG/aON3Ch9arzWywGtd68heOd290wD/MR5Ng12GNQstKUzwAybGG70NERqNXyaVbK9DKd7tPzL4kATdDgoGlEQiEO59wmxvkl7SvVjuUjLG3jCZsjvuy48Zb59ps/ZpDW3pAzLuH9hdky+0yliuUYgCNlsS2zyknziTDoBkSlxkd/yaCas + + + + + \ No newline at end of file