keycloak-uncached

KEYCLOAK-4377

6/27/2017 4:27:36 AM

Details

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 4451b8c..ce5b77f 100755
--- a/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
+++ b/services/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java
@@ -54,7 +54,6 @@ import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
 import org.keycloak.saml.common.exceptions.ConfigurationException;
 import org.keycloak.saml.common.exceptions.ProcessingException;
 import org.keycloak.saml.common.util.DocumentUtil;
-import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
 import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
 import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
 import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
@@ -88,10 +87,13 @@ import java.util.List;
 import org.keycloak.rotation.HardcodedKeyLocator;
 import org.keycloak.rotation.KeyLocator;
 import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
-import org.w3c.dom.Document;
+import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
 import org.w3c.dom.Element;
 
 import java.util.*;
+import javax.xml.crypto.dsig.XMLSignature;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -517,6 +519,17 @@ public class SAMLEndpoint {
     protected class PostBinding extends Binding {
         @Override
         protected void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException {
+            NodeList nl = documentHolder.getSamlDocument().getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
+            boolean anyElementSigned = (nl != null && nl.getLength() > 0);
+            if ((! anyElementSigned) && (documentHolder.getSamlObject() instanceof ResponseType)) {
+                ResponseType responseType = (ResponseType) documentHolder.getSamlObject();
+                List<ResponseType.RTChoiceType> assertions = responseType.getAssertions();
+                if (! assertions.isEmpty() ) {
+                    // Only relax verification if the response is an authnresponse and contains (encrypted/plaintext) assertion.
+                    // In that case, signature is validated on assertion element
+                    return;
+                }
+            }
             SamlProtocolUtils.verifyDocumentSignature(documentHolder.getSamlDocument(), getIDPKeyLocator());
         }
 
diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java
index 4d200a0..c6d999c 100755
--- a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java
+++ b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java
@@ -27,6 +27,24 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
 
     public static final XmlKeyInfoKeyNameTransformer DEFAULT_XML_KEY_INFO_KEY_NAME_TRANSFORMER = XmlKeyInfoKeyNameTransformer.NONE;
 
+    public static final String ADD_EXTENSIONS_ELEMENT_WITH_KEY_INFO = "addExtensionsElementWithKeyInfo";
+    public static final String BACKCHANNEL_SUPPORTED = "backchannelSupported";
+    public static final String ENCRYPTION_PUBLIC_KEY = "encryptionPublicKey";
+    public static final String FORCE_AUTHN = "forceAuthn";
+    public static final String NAME_ID_POLICY_FORMAT = "nameIDPolicyFormat";
+    public static final String POST_BINDING_AUTHN_REQUEST = "postBindingAuthnRequest";
+    public static final String POST_BINDING_LOGOUT = "postBindingLogout";
+    public static final String POST_BINDING_RESPONSE = "postBindingResponse";
+    public static final String SIGNATURE_ALGORITHM = "signatureAlgorithm";
+    public static final String SIGNING_CERTIFICATE_KEY = "signingCertificate";
+    public static final String SINGLE_LOGOUT_SERVICE_URL = "singleLogoutServiceUrl";
+    public static final String SINGLE_SIGN_ON_SERVICE_URL = "singleSignOnServiceUrl";
+    public static final String VALIDATE_SIGNATURE = "validateSignature";
+    public static final String WANT_ASSERTIONS_ENCRYPTED = "wantAssertionsEncrypted";
+    public static final String WANT_ASSERTIONS_SIGNED = "wantAssertionsSigned";
+    public static final String WANT_AUTHN_REQUESTS_SIGNED = "wantAuthnRequestsSigned";
+    public static final String XML_SIG_KEY_INFO_KEY_NAME_TRANSFORMER = "xmlSigKeyInfoKeyNameTransformer";
+
     public SAMLIdentityProviderConfig() {
     }
 
@@ -35,35 +53,35 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
     }
 
     public String getSingleSignOnServiceUrl() {
-        return getConfig().get("singleSignOnServiceUrl");
+        return getConfig().get(SINGLE_SIGN_ON_SERVICE_URL);
     }
 
     public void setSingleSignOnServiceUrl(String singleSignOnServiceUrl) {
-        getConfig().put("singleSignOnServiceUrl", singleSignOnServiceUrl);
+        getConfig().put(SINGLE_SIGN_ON_SERVICE_URL, singleSignOnServiceUrl);
     }
 
     public String getSingleLogoutServiceUrl() {
-        return getConfig().get("singleLogoutServiceUrl");
+        return getConfig().get(SINGLE_LOGOUT_SERVICE_URL);
     }
 
     public void setSingleLogoutServiceUrl(String singleLogoutServiceUrl) {
-        getConfig().put("singleLogoutServiceUrl", singleLogoutServiceUrl);
+        getConfig().put(SINGLE_LOGOUT_SERVICE_URL, singleLogoutServiceUrl);
     }
 
     public boolean isValidateSignature() {
-        return Boolean.valueOf(getConfig().get("validateSignature"));
+        return Boolean.valueOf(getConfig().get(VALIDATE_SIGNATURE));
     }
 
     public void setValidateSignature(boolean validateSignature) {
-        getConfig().put("validateSignature", String.valueOf(validateSignature));
+        getConfig().put(VALIDATE_SIGNATURE, String.valueOf(validateSignature));
     }
 
     public boolean isForceAuthn() {
-        return Boolean.valueOf(getConfig().get("forceAuthn"));
+        return Boolean.valueOf(getConfig().get(FORCE_AUTHN));
     }
 
     public void setForceAuthn(boolean forceAuthn) {
-        getConfig().put("forceAuthn", String.valueOf(forceAuthn));
+        getConfig().put(FORCE_AUTHN, String.valueOf(forceAuthn));
     }
 
     /**
@@ -103,82 +121,80 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
         return crt.split(",");
     }
 
-    public static final String SIGNING_CERTIFICATE_KEY = "signingCertificate";
-
     public String getNameIDPolicyFormat() {
-        return getConfig().get("nameIDPolicyFormat");
+        return getConfig().get(NAME_ID_POLICY_FORMAT);
     }
 
     public void setNameIDPolicyFormat(String nameIDPolicyFormat) {
-        getConfig().put("nameIDPolicyFormat", nameIDPolicyFormat);
+        getConfig().put(NAME_ID_POLICY_FORMAT, nameIDPolicyFormat);
     }
 
     public boolean isWantAuthnRequestsSigned() {
-        return Boolean.valueOf(getConfig().get("wantAuthnRequestsSigned"));
+        return Boolean.valueOf(getConfig().get(WANT_AUTHN_REQUESTS_SIGNED));
     }
 
     public void setWantAuthnRequestsSigned(boolean wantAuthnRequestsSigned) {
-        getConfig().put("wantAuthnRequestsSigned", String.valueOf(wantAuthnRequestsSigned));
+        getConfig().put(WANT_AUTHN_REQUESTS_SIGNED, String.valueOf(wantAuthnRequestsSigned));
     }
 
     public boolean isWantAssertionsSigned() {
-        return Boolean.valueOf(getConfig().get("wantAssertionsSigned"));
+        return Boolean.valueOf(getConfig().get(WANT_ASSERTIONS_SIGNED));
     }
 
     public void setWantAssertionsSigned(boolean wantAssertionsSigned) {
-        getConfig().put("wantAssertionsSigned", String.valueOf(wantAssertionsSigned));
+        getConfig().put(WANT_ASSERTIONS_SIGNED, String.valueOf(wantAssertionsSigned));
     }
 
     public boolean isWantAssertionsEncrypted() {
-        return Boolean.valueOf(getConfig().get("wantAssertionsEncrypted"));
+        return Boolean.valueOf(getConfig().get(WANT_ASSERTIONS_ENCRYPTED));
     }
 
     public void setWantAssertionsEncrypted(boolean wantAssertionsEncrypted) {
-        getConfig().put("wantAssertionsEncrypted", String.valueOf(wantAssertionsEncrypted));
+        getConfig().put(WANT_ASSERTIONS_ENCRYPTED, String.valueOf(wantAssertionsEncrypted));
     }
 
     public boolean isAddExtensionsElementWithKeyInfo() {
-        return Boolean.valueOf(getConfig().get("addExtensionsElementWithKeyInfo"));
+        return Boolean.valueOf(getConfig().get(ADD_EXTENSIONS_ELEMENT_WITH_KEY_INFO));
     }
 
     public void setAddExtensionsElementWithKeyInfo(boolean addExtensionsElementWithKeyInfo) {
-        getConfig().put("addExtensionsElementWithKeyInfo", String.valueOf(addExtensionsElementWithKeyInfo));
+        getConfig().put(ADD_EXTENSIONS_ELEMENT_WITH_KEY_INFO, String.valueOf(addExtensionsElementWithKeyInfo));
     }
 
     public String getSignatureAlgorithm() {
-        return getConfig().get("signatureAlgorithm");
+        return getConfig().get(SIGNATURE_ALGORITHM);
     }
 
     public void setSignatureAlgorithm(String signatureAlgorithm) {
-        getConfig().put("signatureAlgorithm", signatureAlgorithm);
+        getConfig().put(SIGNATURE_ALGORITHM, signatureAlgorithm);
     }
 
     public String getEncryptionPublicKey() {
-        return getConfig().get("encryptionPublicKey");
+        return getConfig().get(ENCRYPTION_PUBLIC_KEY);
     }
 
     public void setEncryptionPublicKey(String encryptionPublicKey) {
-        getConfig().put("encryptionPublicKey", encryptionPublicKey);
+        getConfig().put(ENCRYPTION_PUBLIC_KEY, encryptionPublicKey);
     }
 
     public boolean isPostBindingAuthnRequest() {
-        return Boolean.valueOf(getConfig().get("postBindingAuthnRequest"));
+        return Boolean.valueOf(getConfig().get(POST_BINDING_AUTHN_REQUEST));
     }
 
     public void setPostBindingAuthnRequest(boolean postBindingAuthnRequest) {
-        getConfig().put("postBindingAuthnRequest", String.valueOf(postBindingAuthnRequest));
+        getConfig().put(POST_BINDING_AUTHN_REQUEST, String.valueOf(postBindingAuthnRequest));
     }
 
     public boolean isPostBindingResponse() {
-        return Boolean.valueOf(getConfig().get("postBindingResponse"));
+        return Boolean.valueOf(getConfig().get(POST_BINDING_RESPONSE));
     }
 
     public void setPostBindingResponse(boolean postBindingResponse) {
-        getConfig().put("postBindingResponse", String.valueOf(postBindingResponse));
+        getConfig().put(POST_BINDING_RESPONSE, String.valueOf(postBindingResponse));
     }
 
     public boolean isPostBindingLogout() {
-        String postBindingLogout = getConfig().get("postBindingLogout");
+        String postBindingLogout = getConfig().get(POST_BINDING_LOGOUT);
         if (postBindingLogout == null) {
             // To maintain unchanged behavior when adding this field, we set the inital value to equal that
             // of the binding for the response:
@@ -188,15 +204,15 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
     }
 
     public void setPostBindingLogout(boolean postBindingLogout) {
-        getConfig().put("postBindingLogout", String.valueOf(postBindingLogout));
+        getConfig().put(POST_BINDING_LOGOUT, String.valueOf(postBindingLogout));
     }
 
     public boolean isBackchannelSupported() {
-        return Boolean.valueOf(getConfig().get("backchannelSupported"));
+        return Boolean.valueOf(getConfig().get(BACKCHANNEL_SUPPORTED));
     }
 
     public void setBackchannelSupported(boolean backchannel) {
-        getConfig().put("backchannelSupported", String.valueOf(backchannel));
+        getConfig().put(BACKCHANNEL_SUPPORTED, String.valueOf(backchannel));
     }
 
     /**
@@ -204,11 +220,11 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
      * @return Configured ransformer of {@link #DEFAULT_XML_KEY_INFO_KEY_NAME_TRANSFORMER} if not set.
      */
     public XmlKeyInfoKeyNameTransformer getXmlSigKeyInfoKeyNameTransformer() {
-        return XmlKeyInfoKeyNameTransformer.from(getConfig().get("xmlSigKeyInfoKeyNameTransformer"), DEFAULT_XML_KEY_INFO_KEY_NAME_TRANSFORMER);
+        return XmlKeyInfoKeyNameTransformer.from(getConfig().get(XML_SIG_KEY_INFO_KEY_NAME_TRANSFORMER), DEFAULT_XML_KEY_INFO_KEY_NAME_TRANSFORMER);
     }
 
     public void setXmlSigKeyInfoKeyNameTransformer(XmlKeyInfoKeyNameTransformer xmlSigKeyInfoKeyNameTransformer) {
-        getConfig().put("xmlSigKeyInfoKeyNameTransformer",
+        getConfig().put(XML_SIG_KEY_INFO_KEY_NAME_TRANSFORMER,
           xmlSigKeyInfoKeyNameTransformer == null
             ? null
             : xmlSigKeyInfoKeyNameTransformer.name());
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index a8218c1..caa9709 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -193,7 +193,7 @@ public class SamlProtocol implements LoginProtocol {
                     if (samlClient.requiresEncryption()) {
                         PublicKey publicKey;
                         try {
-                            publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
+                            publicKey = SamlProtocolUtils.getEncryptionKey(client);
                         } catch (Exception e) {
                             logger.error("failed", e);
                             return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
@@ -457,7 +457,7 @@ public class SamlProtocol implements LoginProtocol {
         if (samlClient.requiresEncryption()) {
             PublicKey publicKey = null;
             try {
-                publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
+                publicKey = SamlProtocolUtils.getEncryptionKey(client);
             } catch (Exception e) {
                 logger.error("failed", e);
                 return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
diff --git a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
index 026a54a..7ab97a4 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/SamlProtocolUtils.java
@@ -103,7 +103,7 @@ public class SamlProtocolUtils {
      * @return Public key for encryption.
      * @throws VerificationException
      */
-    public static PublicKey getEncryptionValidationKey(ClientModel client) throws VerificationException {
+    public static PublicKey getEncryptionKey(ClientModel client) throws VerificationException {
         return getPublicKey(client, SamlConfigAttributes.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE);
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/IdentityProviderAttributeUpdater.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/IdentityProviderAttributeUpdater.java
new file mode 100644
index 0000000..b8eb487
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/IdentityProviderAttributeUpdater.java
@@ -0,0 +1,55 @@
+package org.keycloak.testsuite.updaters;
+
+import org.keycloak.admin.client.resource.IdentityProviderResource;
+import org.keycloak.representations.idm.IdentityProviderRepresentation;
+import java.io.Closeable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author hmlnarik
+ */
+public class IdentityProviderAttributeUpdater {
+
+    private final Map<String, String> originalAttributes = new HashMap<>();
+
+    private final IdentityProviderResource identityProviderResource;
+
+    private final IdentityProviderRepresentation rep;
+
+    public IdentityProviderAttributeUpdater(IdentityProviderResource identityProviderResource) {
+        this.identityProviderResource = identityProviderResource;
+        this.rep = identityProviderResource.toRepresentation();
+        if (this.rep.getConfig() == null) {
+            this.rep.setConfig(new HashMap<>());
+        }
+    }
+
+    public IdentityProviderAttributeUpdater setAttribute(String name, String value) {
+        if (! originalAttributes.containsKey(name)) {
+            this.originalAttributes.put(name, this.rep.getConfig().put(name, value));
+        } else {
+            this.rep.getConfig().put(name, value);
+        }
+        return this;
+    }
+
+    public IdentityProviderAttributeUpdater removeAttribute(String name) {
+        if (! originalAttributes.containsKey(name)) {
+            this.originalAttributes.put(name, this.rep.getConfig().put(name, null));
+        } else {
+            this.rep.getConfig().put(name, null);
+        }
+        return this;
+    }
+
+    public Closeable update() {
+        identityProviderResource.update(rep);
+
+        return () -> {
+            rep.getConfig().putAll(originalAttributes);
+            identityProviderResource.update(rep);
+        };
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
index 420fad8..26c398c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.testsuite.adapter.servlet;
 
+import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpUriRequest;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBrokerTest.java
index 6500ad0..6332dd0 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBrokerTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBrokerTest.java
@@ -1,6 +1,5 @@
 package org.keycloak.testsuite.broker;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -14,7 +13,6 @@ import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.testsuite.Assert;
-import org.keycloak.testsuite.admin.ApiUtil;
 import org.keycloak.testsuite.pages.ConsentPage;
 import org.keycloak.testsuite.util.*;
 
@@ -40,6 +38,8 @@ import static org.keycloak.testsuite.broker.BrokerTestTools.*;
 
 public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
 
+    protected IdentityProviderResource identityProviderResource;
+
     @Before
     public void beforeBrokerTest() {
         log.debug("creating user for realm " + bc.providerRealmName());
@@ -61,7 +61,8 @@ public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
 
         log.debug("adding identity provider to realm " + bc.consumerRealmName());
         RealmResource realm = adminClient.realm(bc.consumerRealmName());
-        realm.identityProviders().create(bc.setUpIdentityProvider(suiteContext));
+        realm.identityProviders().create(bc.setUpIdentityProvider(suiteContext)).close();
+        identityProviderResource = realm.identityProviders().get(bc.getIDPAlias());
 
         // addClients
         List<ClientRepresentation> clients = bc.createProviderClients(suiteContext);
@@ -70,7 +71,7 @@ public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
             for (ClientRepresentation client : clients) {
                 log.debug("adding client " + client.getName() + " to realm " + bc.providerRealmName());
 
-                providerRealm.clients().create(client);
+                providerRealm.clients().create(client).close();
             }
         }
 
@@ -80,7 +81,7 @@ public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
             for (ClientRepresentation client : clients) {
                 log.debug("adding client " + client.getName() + " to realm " + bc.consumerRealmName());
 
-                consumerRealm.clients().create(client);
+                consumerRealm.clients().create(client).close();
             }
         }
 
@@ -90,6 +91,12 @@ public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
 
     @Test
     public void testLogInAsUserInIDP() {
+        loginUser();
+
+        testSingleLogout();
+    }
+
+    protected void loginUser() {
         driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
 
         log.debug("Clicking social " + bc.getIDPAlias());
@@ -98,16 +105,16 @@ public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
         waitForPage(driver, "log in to");
 
         Assert.assertTrue("Driver should be on the provider realm page right now",
-                driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
+          driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
 
         log.debug("Logging in");
         accountLoginPage.login(bc.getUserLogin(), bc.getUserPassword());
 
         waitForPage(driver, "update account information");
 
-        Assert.assertTrue(updateAccountInformationPage.isCurrent());
+        updateAccountInformationPage.assertCurrent();
         Assert.assertTrue("We must be on correct realm right now",
-                driver.getCurrentUrl().contains("/auth/realms/" + bc.consumerRealmName() + "/"));
+          driver.getCurrentUrl().contains("/auth/realms/" + bc.consumerRealmName() + "/"));
 
         log.debug("Updating info on updateAccount page");
         updateAccountInformationPage.updateAccountInformation(bc.getUserLogin(), bc.getUserEmail(), "Firstname", "Lastname");
@@ -128,9 +135,7 @@ public abstract class AbstractBrokerTest extends AbstractBaseBrokerTest {
         }
 
         Assert.assertTrue("There must be user " + bc.getUserLogin() + " in realm " + bc.consumerRealmName(),
-                isUserFound);
-
-        testSingleLogout();
+          isUserFound);
     }
 
     @Test
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlBrokerConfiguration.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlBrokerConfiguration.java
index e5f5b8d..da0bc2b 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlBrokerConfiguration.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlBrokerConfiguration.java
@@ -6,6 +6,7 @@
 package org.keycloak.testsuite.broker;
 
 import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.protocol.saml.SamlConfigAttributes;
 import org.keycloak.protocol.saml.SamlProtocol;
 import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
 import org.keycloak.protocol.saml.mappers.UserAttributeStatementMapper;
@@ -22,6 +23,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.keycloak.broker.saml.SAMLIdentityProviderConfig.*;
 import static org.keycloak.testsuite.broker.BrokerTestConstants.*;
 import static org.keycloak.testsuite.broker.BrokerTestTools.*;
 
@@ -63,17 +65,17 @@ public class KcSamlBrokerConfiguration implements BrokerConfiguration {
 
         Map<String, String> attributes = new HashMap<>();
 
-        attributes.put("saml.authnstatement", "true");
-        attributes.put("saml_single_logout_service_url_post",
+        attributes.put(SamlConfigAttributes.SAML_AUTHNSTATEMENT, "true");
+        attributes.put(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE,
                 getAuthRoot(suiteContext) + "/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_SAML_ALIAS + "/endpoint");
-        attributes.put("saml_assertion_consumer_url_post",
+        attributes.put(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE,
                 getAuthRoot(suiteContext) + "/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_SAML_ALIAS + "/endpoint");
-        attributes.put("saml_force_name_id_format", "true");
-        attributes.put("saml_name_id_format", "username");
-        attributes.put("saml.assertion.signature", "false");
-        attributes.put("saml.server.signature", "false");
-        attributes.put("saml.client.signature", "false");
-        attributes.put("saml.encrypt", "false");
+        attributes.put(SamlConfigAttributes.SAML_FORCE_NAME_ID_FORMAT_ATTRIBUTE, "true");
+        attributes.put(SamlConfigAttributes.SAML_NAME_ID_FORMAT_ATTRIBUTE, "username");
+        attributes.put(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE, "false");
+        attributes.put(SamlConfigAttributes.SAML_SERVER_SIGNATURE, "false");
+        attributes.put(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE, "false");
+        attributes.put(SamlConfigAttributes.SAML_ENCRYPT, "false");
 
         client.setAttributes(attributes);
 
@@ -133,15 +135,15 @@ public class KcSamlBrokerConfiguration implements BrokerConfiguration {
 
         Map<String, String> config = idp.getConfig();
 
-        config.put("singleSignOnServiceUrl", getAuthRoot(suiteContext) + "/auth/realms/" + REALM_PROV_NAME + "/protocol/saml");
-        config.put("singleLogoutServiceUrl", getAuthRoot(suiteContext) + "/auth/realms/" + REALM_PROV_NAME + "/protocol/saml");
-        config.put("nameIDPolicyFormat", "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
-        config.put("forceAuthn", "true");
-        config.put("postBindingResponse", "true");
-        config.put("postBindingAuthnRequest", "true");
-        config.put("validateSignature", "false");
-        config.put("wantAuthnRequestsSigned", "false");
-        config.put("backchannelSupported", "true");
+        config.put(SINGLE_SIGN_ON_SERVICE_URL, getAuthRoot(suiteContext) + "/auth/realms/" + REALM_PROV_NAME + "/protocol/saml");
+        config.put(SINGLE_LOGOUT_SERVICE_URL, getAuthRoot(suiteContext) + "/auth/realms/" + REALM_PROV_NAME + "/protocol/saml");
+        config.put(NAME_ID_POLICY_FORMAT, "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
+        config.put(FORCE_AUTHN, "true");
+        config.put(POST_BINDING_RESPONSE, "true");
+        config.put(POST_BINDING_AUTHN_REQUEST, "true");
+        config.put(VALIDATE_SIGNATURE, "false");
+        config.put(WANT_AUTHN_REQUESTS_SIGNED, "false");
+        config.put(BACKCHANNEL_SUPPORTED, "true");
 
         return idp;
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java
index b4825cd..ef23a9a 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java
@@ -1,19 +1,29 @@
 package org.keycloak.testsuite.broker;
 
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
+import org.keycloak.protocol.saml.SamlConfigAttributes;
 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 org.keycloak.testsuite.updaters.ClientAttributeUpdater;
+import org.keycloak.testsuite.updaters.IdentityProviderAttributeUpdater;
+import java.io.Closeable;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
 import static org.keycloak.testsuite.broker.BrokerTestConstants.*;
+import static org.keycloak.testsuite.broker.BrokerTestTools.encodeUrl;
 
 public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
 
-    public static class KcSamlSignedBrokerConfiguration extends KcSamlBrokerConfiguration {
+    public class KcSamlSignedBrokerConfiguration extends KcSamlBrokerConfiguration {
 
         @Override
         public RealmRepresentation createProviderRealm() {
@@ -39,6 +49,9 @@ public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
         public List<ClientRepresentation> createProviderClients(SuiteContext suiteContext) {
             List<ClientRepresentation> clientRepresentationList = super.createProviderClients(suiteContext);
 
+            String consumerCert = adminClient.realm(consumerRealmName()).keys().getKeyMetadata().getKeys().get(0).getCertificate();
+            Assert.assertThat(consumerCert, Matchers.notNullValue());
+
             for (ClientRepresentation client : clientRepresentationList) {
                 client.setClientAuthenticatorType("client-secret");
                 client.setSurrogateAuthRequired(false);
@@ -49,12 +62,11 @@ public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
                     client.setAttributes(attributes);
                 }
 
-                attributes.put("saml.assertion.signature", "true");
-                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);
+                attributes.put(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE, "true");
+                attributes.put(SamlConfigAttributes.SAML_SERVER_SIGNATURE, "true");
+                attributes.put(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE, "true");
+                attributes.put(SamlConfigAttributes.SAML_SIGNATURE_ALGORITHM, "RSA_SHA256");
+                attributes.put(SamlConfigAttributes.SAML_SIGNING_CERTIFICATE_ATTRIBUTE, consumerCert);
             }
 
             return clientRepresentationList;
@@ -64,11 +76,15 @@ public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
         public IdentityProviderRepresentation setUpIdentityProvider(SuiteContext suiteContext) {
             IdentityProviderRepresentation result = super.setUpIdentityProvider(suiteContext);
 
+            String providerCert = adminClient.realm(providerRealmName()).keys().getKeyMetadata().getKeys().get(0).getCertificate();
+            Assert.assertThat(providerCert, Matchers.notNullValue());
+
             Map<String, String> config = result.getConfig();
 
-            config.put("validateSignature", "true");
-            config.put("wantAuthnRequestsSigned", "true");
-            config.put("signingCertificate", IDP_SAML_SIGN_CERT);
+            config.put(SAMLIdentityProviderConfig.VALIDATE_SIGNATURE, "true");
+            config.put(SAMLIdentityProviderConfig.WANT_ASSERTIONS_SIGNED, "true");
+            config.put(SAMLIdentityProviderConfig.WANT_AUTHN_REQUESTS_SIGNED, "true");
+            config.put(SAMLIdentityProviderConfig.SIGNING_CERTIFICATE_KEY, providerCert);
 
             return result;
         }
@@ -76,7 +92,50 @@ public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
 
     @Override
     protected BrokerConfiguration getBrokerConfiguration() {
-        return KcSamlSignedBrokerConfiguration.INSTANCE;
+        return new KcSamlSignedBrokerConfiguration();
     }
 
+    @Test
+    public void testSignedEncryptedAssertions() throws Exception {
+        ClientRepresentation client = adminClient.realm(bc.providerRealmName())
+          .clients()
+          .findByClientId(bc.getIDPClientIdInProviderRealm(suiteContext))
+          .get(0);
+
+        final ClientResource clientResource = realmsResouce().realm(bc.providerRealmName()).clients().get(client.getId());
+        Assert.assertThat(clientResource, Matchers.notNullValue());
+
+        String providerCert = adminClient.realm(bc.providerRealmName()).keys().getKeyMetadata().getKeys().get(0).getCertificate();
+        Assert.assertThat(providerCert, Matchers.notNullValue());
+
+        String consumerCert = adminClient.realm(bc.consumerRealmName()).keys().getKeyMetadata().getKeys().get(0).getCertificate();
+        Assert.assertThat(consumerCert, Matchers.notNullValue());
+
+        try (Closeable idpUpdater = new IdentityProviderAttributeUpdater(identityProviderResource)
+            .setAttribute(SAMLIdentityProviderConfig.VALIDATE_SIGNATURE, "true")
+            .setAttribute(SAMLIdentityProviderConfig.WANT_ASSERTIONS_SIGNED, "true")
+            .setAttribute(SAMLIdentityProviderConfig.WANT_ASSERTIONS_ENCRYPTED, "true")
+            .setAttribute(SAMLIdentityProviderConfig.WANT_AUTHN_REQUESTS_SIGNED, "false")
+            .setAttribute(SAMLIdentityProviderConfig.SIGNING_CERTIFICATE_KEY, providerCert)
+            .update();
+          Closeable clientUpdater = new ClientAttributeUpdater(clientResource)
+            .setAttribute(SamlConfigAttributes.SAML_ENCRYPT, "true")
+            .setAttribute(SamlConfigAttributes.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE, consumerCert)
+            .setAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE, "false")      // only sign assertions
+            .setAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE, "true")
+            .setAttribute(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE, "false")
+            .update())
+        {
+            // Login should pass because assertion is signed.
+            loginUser();
+
+            // Logout should fail because logout response is not signed.
+            driver.navigate().to(BrokerTestTools.getAuthRoot(suiteContext)
+                    + "/auth/realms/" + bc.providerRealmName()
+                    + "/protocol/" + "openid-connect"
+                    + "/logout?redirect_uri=" + encodeUrl(getAccountUrl(bc.providerRealmName())));
+
+            errorPage.assertCurrent();
+        }
+    }
 }