diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/DocumentUtil.java b/saml-core/src/main/java/org/keycloak/saml/common/util/DocumentUtil.java index b5f2232a47..f516124f7b 100755 --- a/saml-core/src/main/java/org/keycloak/saml/common/util/DocumentUtil.java +++ b/saml-core/src/main/java/org/keycloak/saml/common/util/DocumentUtil.java @@ -52,6 +52,7 @@ import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; +import java.util.Objects; /** * Utility dealing with DOM @@ -554,4 +555,33 @@ public class DocumentUtil { return documentBuilderFactory; } + + /** + * Get a (direct) child {@linkplain Element} from the parent {@linkplain Element}. + * + * @param parent parent element + * @param targetNamespace namespace URI + * @param targetLocalName local name + * @return a child element matching the target namespace and localname, where {@linkplain Element#getParentNode()} is the parent input parameter + * @return + */ + + public static Element getDirectChildElement(Element parent, String targetNamespace, String targetLocalName) { + Node child = parent.getFirstChild(); + + while(child != null) { + if(child instanceof Element) { + Element childElement = (Element)child; + + String ns = childElement.getNamespaceURI(); + String localName = childElement.getLocalName(); + + if(Objects.equals(targetNamespace, ns) && Objects.equals(targetLocalName, localName)) { + return childElement; + } + } + child = child.getNextSibling(); + } + return null; + } } \ No newline at end of file diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java index ef3e3bd736..09ce9d62f8 100755 --- a/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java +++ b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java @@ -49,8 +49,6 @@ public class SAML2Signature { private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); - private static final String ID_ATTRIBUTE_NAME = "ID"; - private String signatureMethod = SignatureMethod.RSA_SHA1; private String digestMethod = DigestMethod.SHA1; @@ -156,7 +154,7 @@ public class SAML2Signature { */ public void signSAMLDocument(Document samlDocument, String keyName, KeyPair keypair, String canonicalizationMethodType) throws ProcessingException { // Get the ID from the root - String id = samlDocument.getDocumentElement().getAttribute(ID_ATTRIBUTE_NAME); + String id = samlDocument.getDocumentElement().getAttribute(JBossSAMLConstants.ID.get()); try { sign(samlDocument, id, keyName, keypair, canonicalizationMethodType); } catch (ParserConfigurationException | GeneralSecurityException | MarshalException | XMLSignatureException e) { @@ -210,18 +208,20 @@ public class SAML2Signature { * * @param document SAML document to have its ID attribute configured. */ - private void configureIdAttribute(Document document) { + public static void configureIdAttribute(Document document) { // Estabilish the IDness of the ID attribute. - document.getDocumentElement().setIdAttribute(ID_ATTRIBUTE_NAME, true); + configureIdAttribute(document.getDocumentElement()); NodeList nodes = document.getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()); for (int i = 0; i < nodes.getLength(); i++) { - Node n = nodes.item(i); - if (n instanceof Element) { - ((Element) n).setIdAttribute(ID_ATTRIBUTE_NAME, true); - } + configureIdAttribute((Element) nodes.item(i)); } } + + public static void configureIdAttribute(Element element) { + element.setIdAttribute(JBossSAMLConstants.ID.get(), true); + } + } \ No newline at end of file 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 bb15d233bf..244fb7d182 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 @@ -49,11 +49,12 @@ import org.keycloak.saml.processing.core.parsers.saml.SAMLParser; import org.keycloak.saml.processing.core.saml.v2.writers.SAMLAssertionWriter; import org.keycloak.saml.processing.core.util.JAXPValidationUtil; import org.keycloak.saml.processing.core.util.XMLEncryptionUtil; - +import org.keycloak.saml.processing.core.util.XMLSignatureUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; +import javax.xml.crypto.dsig.XMLSignature; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; import java.io.ByteArrayInputStream; @@ -267,42 +268,56 @@ public class AssertionUtil { } /** - * Given an assertion element, validate the signature + * Given an {@linkplain Element}, validate the Signature direct child element * - * @param assertionElement + * @param element parent {@linkplain Element} * @param publicKey the {@link PublicKey} * - * @return + * @return true if signature is present and valid */ - public static boolean isSignatureValid(Element assertionElement, PublicKey publicKey) { - try { - Document doc = DocumentUtil.createDocument(); - Node n = doc.importNode(assertionElement, true); - doc.appendChild(n); - - return new SAML2Signature().validate(doc, new HardcodedKeyLocator(publicKey)); - } catch (Exception e) { - logger.signatureAssertionValidationError(e); - } - return false; + public static boolean isSignatureValid(Element element, PublicKey publicKey) { + return isSignatureValid(element, new HardcodedKeyLocator(publicKey)); } /** - * Given an assertion element, validate the signature. + * Given an {@linkplain Element}, validate the Signature direct child element + * + * @param element parent {@linkplain Element} + * @param keyLocator the {@link KeyLocator} + * + * @return true if signature is present and valid */ - public static boolean isSignatureValid(Element assertionElement, KeyLocator keyLocator) { + + public static boolean isSignatureValid(Element element, KeyLocator keyLocator) { try { - Document doc = DocumentUtil.createDocument(); - Node n = doc.importNode(assertionElement, true); - doc.appendChild(n); - - return new SAML2Signature().validate(doc, keyLocator); + SAML2Signature.configureIdAttribute(element); + + Element signature = getSignature(element); + if(signature != null) { + return XMLSignatureUtil.validateSingleNode(signature, keyLocator); + } } catch (Exception e) { logger.signatureAssertionValidationError(e); } return false; } + + /** + * + * Given an {@linkplain Element}, check if there is a Signature direct child element + * + * @param element parent {@linkplain Element} + * @return true if signature is present + */ + public static boolean isSignedElement(Element element) { + return getSignature(element) != null; + } + + protected static Element getSignature(Element element) { + return DocumentUtil.getDirectChildElement(element, XMLSignature.XMLNS, "Signature"); + } + /** * Check whether the assertion has expired * @@ -570,8 +585,8 @@ public class AssertionUtil { /** * This method modifies the given responseType, and replaces the encrypted assertion with a decrypted version. - * - * It returns the assertion element as it was decrypted. This can be used in sginature verification. + * @param responseType a response containg an encrypted assertion + * @return the assertion element as it was decrypted. This can be used in signature verification. */ public static Element decryptAssertion(ResponseType responseType, PrivateKey privateKey) throws ParsingException, ProcessingException, ConfigurationException { SAML2Response saml2Response = new SAML2Response(); diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java index 53228c971a..7093a20391 100755 --- a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java +++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/XMLSignatureUtil.java @@ -468,7 +468,7 @@ public class XMLSignatureUtil { return true; } - private static boolean validateSingleNode(Node signatureNode, final KeyLocator locator) throws MarshalException, XMLSignatureException { + public static boolean validateSingleNode(Node signatureNode, final KeyLocator locator) throws MarshalException, XMLSignatureException { KeySelectorUtilizingKeyNameHint sel = new KeySelectorUtilizingKeyNameHint(locator); try { if (validateUsingKeySelector(signatureNode, sel)) { diff --git a/saml-core/src/test/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtilTest.java b/saml-core/src/test/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtilTest.java new file mode 100644 index 0000000000..b60bb4b893 --- /dev/null +++ b/saml-core/src/test/java/org/keycloak/saml/processing/core/saml/v2/util/AssertionUtilTest.java @@ -0,0 +1,58 @@ +package org.keycloak.saml.processing.core.saml.v2.util; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.cert.X509Certificate; + +import org.bouncycastle.util.Arrays; +import org.junit.Test; +import org.keycloak.common.util.Base64; +import org.keycloak.common.util.DerUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class AssertionUtilTest { + + private static final String PRIVATE_KEY = "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw=="; + + /** + * The public certificate that corresponds to {@link #PRIVATE_KEY}. + */ + private static final String PUBLIC_CERT = "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin"; + + @Test + public void testSaml20Signed() throws Exception { + + X509Certificate decodeCertificate = DerUtils.decodeCertificate(new ByteArrayInputStream(Base64.decode(PUBLIC_CERT))); + + try (InputStream st = AssertionUtilTest.class.getResourceAsStream("saml20-signed-response.xml")) { + Document document = DocumentUtil.getDocument(st); + + Element assertion = DocumentUtil.getDirectChildElement(document.getDocumentElement(), "urn:oasis:names:tc:SAML:2.0:assertion", "Assertion"); + + assertTrue(AssertionUtil.isSignatureValid(assertion, decodeCertificate.getPublicKey())); + + // test manipulation of signature + Element signatureElement = AssertionUtil.getSignature(assertion); + byte[] validSignature = Base64.decode(signatureElement.getTextContent()); + + // change the signature value slightly + byte[] invalidSignature = Arrays.clone(validSignature); + invalidSignature[0] ^= invalidSignature[0]; + signatureElement.setTextContent(Base64.encodeBytes(invalidSignature)); + + // check that signature now is invalid + assertFalse(AssertionUtil.isSignatureValid(document.getDocumentElement(), decodeCertificate.getPublicKey())); + + // restore valid signature, but remove Signature element, check that still invalid + signatureElement.setTextContent(Base64.encodeBytes(validSignature)); + + assertion.removeChild(signatureElement); + assertFalse(AssertionUtil.isSignatureValid(document.getDocumentElement(), decodeCertificate.getPublicKey())); + } + } + +} diff --git a/saml-core/src/test/resources/org/keycloak/saml/processing/core/saml/v2/util/saml20-signed-response.xml b/saml-core/src/test/resources/org/keycloak/saml/processing/core/saml/v2/util/saml20-signed-response.xml new file mode 100644 index 0000000000..998520addb --- /dev/null +++ b/saml-core/src/test/resources/org/keycloak/saml/processing/core/saml/v2/util/saml20-signed-response.xml @@ -0,0 +1 @@ +http://localhost:8080/auth/realms/saml-broker-realmhttp://localhost:8080/auth/realms/saml-broker-realmcCSNXxLmu411weW1kRpie4C9yaBg2In6V4oEuqya0Eo=Qe6ZqgSwFH31UTu+zHqr1/UsafH0luxP5OH/cqyHm07Kf/Fp/fm9mnHJ0kGoUn0SUo7xWvwy8AzUfPXWMYS3kDyhUsPzgz0CnCzzfTz3koKFczgyIQ8sokIDv0cTp3z1qCUVWV0CEPzhtWlaIus2W89TEi/h9KjYrkeGl3+cpm8BPEAt4EP8Oht5czK2haIfPMDUm5Y7uw/FCSsvSfFyrlJ0jR/YMeP9PP0InYYegI9QQgvXKRm6DZSNZgKYFpprc12v6vv/zTaMm5fbuuy1wNDuDTB8EF6K1yrq21DatJXUKE1oOMBrkOvbFJNtgHlQviz1OssAqzHlf0NQPIAEig==IzH2UxfMxovYTEHn4Bh-EAj-Zrvldukl_5Snu0RA0B8MIICsTCCAZkCBgFb1GERYzANBgkqhkiG9w0BAQsFADAcMRowGAYDVQQDDBFzYW1sLWJyb2tlci1yZWFsbTAeFw0xNzA1MDQxNjUxMjJaFw0yNzA1MDQxNjUzMDJaMBwxGjAYBgNVBAMMEXNhbWwtYnJva2VyLXJlYWxtMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCBuWKmcVPX4sZtpvBp8BgQwH51l5tKPuQq66/4JH40hzkrLOGcVEOafIsGoOWi8HsZWZu+APwhSrnRNd7yMV+NJyw5W1DKjhdUPWnzPNy+UMAcoUBFhXDIWog0qxgGvTdoe1lfHryUQt1cd95SFVIerJA93nFbSOoMB+N7TmfQm+sNu2pJ2tr6mx3wGCXMnWf29gwhCI3wV19hh4KugnMIEStjvQoRyh2yna64BrR3eaUyhU/Bdrq2VXLNU/9WXg9gbRLUEWkMUPKOeQ5cGCgc4JFyFXRo5ExkzmvP9vwBRtjQulk5QKqfYo251mKvTQgO7K8d4CzVS/4+bpgKvZAMgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQ==AQABG-ebb3a66f-686f-4bb9-8a8b-20b566ca747bhttp://localhost:8080/auth/realms/saml-broker-authentication-realmurn:oasis:names:tc:SAML:2.0:ac:classes:unspecifiedmanageruser \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java b/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java index 5825f60554..b439009c0f 100755 --- a/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java +++ b/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java @@ -371,13 +371,13 @@ public class SAMLEndpoint { assertionElement = DocumentUtil.getElement(holder.getSamlDocument(), new QName(JBossSAMLConstants.ASSERTION.get())); } - if (config.isWantAssertionsSigned() && config.isValidateSignature()) { - if (!AssertionUtil.isSignatureValid(assertionElement, getIDPKeyLocator())) { - logger.error("validation failed"); - event.event(EventType.IDENTITY_PROVIDER_RESPONSE); - event.error(Errors.INVALID_SIGNATURE); - return ErrorPage.error(session, Messages.INVALID_REQUESTER); - } + boolean signed = AssertionUtil.isSignedElement(assertionElement); + if ((config.isWantAssertionsSigned() && !signed) + || (signed && config.isValidateSignature() && !AssertionUtil.isSignatureValid(assertionElement, getIDPKeyLocator()))) { + logger.error("validation failed"); + event.event(EventType.IDENTITY_PROVIDER_RESPONSE); + event.error(Errors.INVALID_SIGNATURE); + return ErrorPage.error(session, Messages.INVALID_REQUESTER); } AssertionType assertion = responseType.getAssertions().get(0).getAssertion(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedDocumentOnlyBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedDocumentOnlyBrokerTest.java new file mode 100644 index 0000000000..5f9fd0e8be --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedDocumentOnlyBrokerTest.java @@ -0,0 +1,83 @@ +package org.keycloak.testsuite.broker; + +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.arquillian.SuiteContext; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.keycloak.testsuite.broker.BrokerTestConstants.*; + +public class KcSamlSignedDocumentOnlyBrokerTest extends KcSamlBrokerTest { + + public static class KcSamlSignedBrokerConfiguration extends KcSamlBrokerConfiguration { + + @Override + public RealmRepresentation createProviderRealm() { + RealmRepresentation realm = super.createProviderRealm(); + + realm.setPublicKey(REALM_PUBLIC_KEY); + realm.setPrivateKey(REALM_PRIVATE_KEY); + + return realm; + } + + @Override + public RealmRepresentation createConsumerRealm() { + RealmRepresentation realm = super.createConsumerRealm(); + + realm.setPublicKey(REALM_PUBLIC_KEY); + realm.setPrivateKey(REALM_PRIVATE_KEY); + + return realm; + } + + @Override + public List createProviderClients(SuiteContext suiteContext) { + List clientRepresentationList = super.createProviderClients(suiteContext); + + for (ClientRepresentation client : clientRepresentationList) { + client.setClientAuthenticatorType("client-secret"); + client.setSurrogateAuthRequired(false); + + Map attributes = client.getAttributes(); + if (attributes == null) { + attributes = new HashMap<>(); + client.setAttributes(attributes); + } + + attributes.put("saml.assertion.signature", "false"); + attributes.put("saml.server.signature", "true"); + attributes.put("saml.client.signature", "true"); + attributes.put("saml.signature.algorithm", "RSA_SHA256"); + attributes.put("saml.signing.private.key", IDP_SAML_SIGN_KEY); + attributes.put("saml.signing.certificate", IDP_SAML_SIGN_CERT); + } + + return clientRepresentationList; + } + + @Override + public IdentityProviderRepresentation setUpIdentityProvider(SuiteContext suiteContext) { + IdentityProviderRepresentation result = super.setUpIdentityProvider(suiteContext); + + Map config = result.getConfig(); + + config.put("validateSignature", "true"); + config.put("wantAssertionsSigned", "false"); + config.put("wantAuthnRequestsSigned", "true"); + config.put("signingCertificate", IDP_SAML_SIGN_CERT); + + return result; + } + } + + @Override + protected BrokerConfiguration getBrokerConfiguration() { + return KcSamlSignedBrokerConfiguration.INSTANCE; + } + +}