Merge pull request #3886 from anderius/feature/newlines-in-saml
KEYCLOAK-4489 SAML encrypted assertion with newlines fails during parsing
This commit is contained in:
commit
5b4e3434bb
3 changed files with 70 additions and 2 deletions
|
@ -41,7 +41,6 @@ import org.keycloak.saml.common.exceptions.ParsingException;
|
||||||
import org.keycloak.saml.common.exceptions.ProcessingException;
|
import org.keycloak.saml.common.exceptions.ProcessingException;
|
||||||
import org.keycloak.saml.common.exceptions.fed.IssueInstantMissingException;
|
import org.keycloak.saml.common.exceptions.fed.IssueInstantMissingException;
|
||||||
import org.keycloak.saml.common.util.DocumentUtil;
|
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.common.util.StaxUtil;
|
||||||
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
|
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
|
||||||
import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
|
import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
|
||||||
|
@ -560,7 +559,7 @@ public class AssertionUtil {
|
||||||
SAMLParser parser = new SAMLParser();
|
SAMLParser parser = new SAMLParser();
|
||||||
|
|
||||||
JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
|
JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
|
||||||
AssertionType assertion = (AssertionType) parser.parse(StaxParserUtil.getXMLEventReader(DocumentUtil
|
AssertionType assertion = (AssertionType) parser.parse(parser.createEventReader(DocumentUtil
|
||||||
.getNodeAsStream(decryptedDocumentElement)));
|
.getNodeAsStream(decryptedDocumentElement)));
|
||||||
|
|
||||||
responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion));
|
responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion));
|
||||||
|
|
|
@ -16,11 +16,16 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.saml.processing.core.parsers.saml;
|
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.AssertionType;
|
||||||
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
||||||
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
|
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
|
||||||
|
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
@ -35,12 +40,22 @@ import org.w3c.dom.Element;
|
||||||
/**
|
/**
|
||||||
* Test class for SAML parser.
|
* 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.
|
* TODO: Add further tests.
|
||||||
*
|
*
|
||||||
* @author hmlnarik
|
* @author hmlnarik
|
||||||
*/
|
*/
|
||||||
public class SAMLParserTest {
|
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;
|
private SAMLParser parser;
|
||||||
|
|
||||||
@Before
|
@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
|
@Test
|
||||||
public void testSaml20EncryptedAssertionsSignedTwoExtensionsReceivedWithRedirectBinding() throws Exception {
|
public void testSaml20EncryptedAssertionsSignedTwoExtensionsReceivedWithRedirectBinding() throws Exception {
|
||||||
Element el;
|
Element el;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||||
|
ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6" Version="2.0" IssueInstant="2014-07-17T01:01:48Z"
|
||||||
|
Destination="http://sp.example.com/demo1/index.php?acs"
|
||||||
|
InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685">
|
||||||
|
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
|
||||||
|
<samlp:Status>
|
||||||
|
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
|
||||||
|
</samlp:Status>
|
||||||
|
|
||||||
|
<saml:EncryptedAssertion>
|
||||||
|
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
|
||||||
|
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
|
||||||
|
Type="http://www.w3.org/2001/04/xmlenc#Element">
|
||||||
|
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
|
||||||
|
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
|
||||||
|
<xenc:EncryptedKey>
|
||||||
|
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
|
||||||
|
<xenc:CipherData>
|
||||||
|
<xenc:CipherValue>
|
||||||
|
BpU+yCD3m1WdIGDfKnMOplsAzVZd/1cJZwu7l8/Rc/pMXxrYBR4m5WGxyKr+YwJoV3n1+CtYzrsklRN3Ck3Z7seRQf3bluWIvruVSS5k7HpTtZmyY/k0/Y0oTRr8z6YJ8MzL9veyM9EVcwIBFZypPN5ep+HDgz06QV0LAlFkGlQ=
|
||||||
|
</xenc:CipherValue>
|
||||||
|
</xenc:CipherData>
|
||||||
|
</xenc:EncryptedKey>
|
||||||
|
</dsig:KeyInfo>
|
||||||
|
<xenc:CipherData>
|
||||||
|
<xenc:CipherValue>
|
||||||
|
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
|
||||||
|
</xenc:CipherValue>
|
||||||
|
</xenc:CipherData>
|
||||||
|
</xenc:EncryptedData>
|
||||||
|
</saml:EncryptedAssertion>
|
||||||
|
</samlp:Response>
|
Loading…
Reference in a new issue