KEYCLOAK-4377

This commit is contained in:
Hynek Mlnarik committed 2017-06-27 14:34:47 +02:00
1 parent 1c10199698
commit a3ccac2012
12 files changed
+233 -82

No files matched your search

@@ -1,4 +1,4 @@
package org.keycloak.testsuite.util;
package org.keycloak.testsuite.updaters;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.representations.idm.ClientRepresentation;
@@ -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);
};
}
}
@@ -1,4 +1,4 @@
package org.keycloak.testsuite.util;
package org.keycloak.testsuite.updaters;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.representations.idm.RealmRepresentation;
@@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.keycloak.testsuite.util;
package org.keycloak.testsuite.updaters;
import java.io.Closeable;
@@ -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;
@@ -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
@@ -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;
}
@@ -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();
}
}
}