diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/broker/BrokerTestConstants.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/broker/BrokerTestConstants.java new file mode 100644 index 0000000000..b2c2b85cb0 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/broker/BrokerTestConstants.java @@ -0,0 +1,85 @@ +package org.keycloak.testsuite.broker; + +class BrokerTestConstants { + + final static String REALM_PROV_NAME = "provider"; + final static String REALM_CONS_NAME = "consumer"; + + final static String IDP_OIDC_ALIAS = "kc-oidc-idp"; + final static String IDP_OIDC_PROVIDER_ID = "keycloak-oidc"; + + final static String IDP_SAML_ALIAS = "kc-saml-idp"; + final static String IDP_SAML_PROVIDER_ID = "saml"; + + final static String CLIENT_ID = "brokerapp"; + final static String CLIENT_SECRET = "secret"; + + final static String USER_LOGIN = "testuser"; + final static String USER_EMAIL = "user@localhost.com"; + final static String USER_PASSWORD = "password"; + + final static String IDP_SAML_SIGN_KEY = "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygc" + + "DfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb4" + + "0tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SV" + + "Er55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3" + + "og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8" + + "ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKp" + + "r/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus" + + "7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiC" + + "KpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9" + + "BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzU" + + "alm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58c" + + "kAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZ" + + "V9wN85V0xZXWsw=="; + + final static String IDP_SAML_SIGN_CERT = "MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG" + + "9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDV" + + "QQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDg" + + "YDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4" + + "GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQ" + + "MA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93b" + + "jCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKr" + + "GTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfm" + + "m2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1F" + + "Vqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNG" + + "txwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBr" + + "cAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFl" + + "cNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD" + + "0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8" + + "C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW" + + "7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8Uei" + + "KAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKm" + + "CV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin"; + + final static String REALM_PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwg" + + "gSkAgEAAoIBAQCCPyvTTb14vSMkpe/pds2P5Cqxk7bkeFnQiNMS1vyZ+HS2O79fxzp1eA" + + "guHnBTs4XTRT7SZJhIT/6utgqZjmDigKV5N7X5ptq8BM/W1qa1cYBRip261pc+tWf3Iyw" + + "JYQ9yFI9mUQarmIEl0D7GH16NSZklheaWfbodRVarvX+ML0amNtGYVDft/RftYmgbKKrK" + + "218qQp9R4GZFtf/Q/RmboNXN7weMINU8GWVkTRrccKBIXSunT6zXGfuj3Wp1YpVq20BWw" + + "Y2OMM/P+yDAc7LKEO1LJqPBdT4r9BRn2lXiaga3AL24gTKZPKU/tu7uqfFciF+i4Rr58S" + + "MDNOzQcnklAgMBAAECggEAc0eibJYEO5d8QXW1kPgcHV2gBChv2mxDYnWYDLbIQSdNdfY" + + "P/qABt/MTmm5KkWr16fcCEYoD1w0mqFBrtVn1msSusUmEAYGTXJMNumOmjjX1kzaTQMmq" + + "eFBrwqwYz/xehWR5P+A7fSmwNV3KEeW19GvN5w5K96w0TLAQdFV3TQVPSytusDunwuR1y" + + "ltMe1voaEDZ9z0Pi08YiEk2f6xhj5CMkoiw3mNImzfruphHullxU4FD05fH6tDeJ38152" + + "7ILpAzDsgYZh4aFLKjUHem96bX4EL7FIzBJ6okgN78AZnUC/EaVfgFTw0qfhoWvZV4ruV" + + "XXiMhCg4CMMRDq/k9iQKBgQDBNWsJMT84OnnWmQoJmZogkFV+tsGrSK6Re+aJxLWpishh" + + "7dwAnT2OcagZvVdUb0FwNWu1D0B9/SKDDMRnnHBhOGDpH57m/eQdRU0oX1BD27xvffk0l" + + "LcfD4BTxnR5e9jss8K4twc9jf0P1rxC/loGJ2NtCH0BrPHgz54Ea+96ewKBgQCsk3JDaa" + + "PnFwzVYm2BXlhxOxLPsF4wvD2rIRAswZV4C5xebjand8nwiMmVpNd0PRLkEnkI+waURGv" + + "2EY/P3JsssoiY8Xqe8f/1G+SQKre7lbqOas8rFoALepC0BYDiZDFy0Z9ZnRAFzRI5sgIt" + + "7jpoMRD4xDNlmiV8X+yBxc3Y3wKBgQChDQsU1YUyNKQ8+sLAL9anEEkD4Ald4q8JPHN2I" + + "Y+gLLxNzT0XEfsu0pTiJ8805axxgUYv3e/PVYNAJBNPnrqaf6lgiegl+jr9Hzhqz9CTUA" + + "YqFaL2boSakoxQyNtsLI0s+cb1vDN/3uy0GDZDzcty18BsMagqDmRtFgNNAj/UIwKBgQC" + + "ahbeFBv0cOPZjxisY8Bou4N8aGehsqNBq/0LVYExuXa8YmoTTdJ3bgw9Er4G/ccQNdUDs" + + "uqAMeCtW/CiRzQ0ge4d1sprB4Rv3I4+HSsiS7SFKzfZLtWzXWlpg5qCdlWr1TR7qhYjIO" + + "PO9t1beO3YOvwhcRoliyyAPenBxTmTfbwKBgDtm2WJ5VlQgNpIdOs1CCiqd0DFmWOmvBP" + + "spPC1kySiy+Ndr9jNohRZkR7pEjgqA5E8rdzc88LirUN7bY5HFHRWN9KXrs5/o3O1K3GF" + + "Cp64N6nvnPEYZ2zSJalcMC2fjSsJg26z8Dg1H+gfTIDUMoGiEAAnJXuqk+WayPU+fZMLn"; + + final static String REALM_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgK" + + "CAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF0" + + "0U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlE" + + "Gq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmR" + + "bX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHO" + + "yyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB"; +} diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/UpdateAccountInformationPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/UpdateAccountInformationPage.java new file mode 100644 index 0000000000..b7b30ed437 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/UpdateAccountInformationPage.java @@ -0,0 +1,62 @@ +package org.keycloak.testsuite.pages; + +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; + +public class UpdateAccountInformationPage extends AbstractPage { + + @FindBy(id = "username") + private WebElement usernameInput; + + @FindBy(id = "email") + private WebElement emailInput; + + @FindBy(id = "firstName") + private WebElement firstNameInput; + + @FindBy(id = "lastName") + private WebElement lastNameInput; + + @FindBy(css = "input[type=\"submit\"]") + private WebElement submitButton; + + public void updateAccountInformation(String userName, + String email, + String firstName, + String lastName) { + usernameInput.clear(); + usernameInput.sendKeys(userName); + + emailInput.clear(); + emailInput.sendKeys(email); + + firstNameInput.clear(); + firstNameInput.sendKeys(firstName); + + lastNameInput.clear(); + lastNameInput.sendKeys(lastName); + + submitButton.click(); + } + + public void updateAccountInformation(String firstName, + String lastName) { + firstNameInput.clear(); + firstNameInput.sendKeys(firstName); + + lastNameInput.clear(); + lastNameInput.sendKeys(lastName); + + submitButton.click(); + } + + @Override + public boolean isCurrent() { + return driver.getTitle().equalsIgnoreCase("update account information"); + } + + @Override + public void open() throws Exception { + + } +} 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 new file mode 100644 index 0000000000..a6a5c06639 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBrokerTest.java @@ -0,0 +1,179 @@ +package org.keycloak.testsuite.broker; + +import org.jboss.arquillian.graphene.page.Page; +import org.junit.Before; +import org.junit.Test; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.admin.client.resource.UsersResource; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.testsuite.AbstractKeycloakTest; +import org.keycloak.testsuite.Assert; +import org.keycloak.testsuite.pages.LoginPage; +import org.keycloak.testsuite.pages.UpdateAccountInformationPage; + +import java.util.List; + +import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient; +import static org.keycloak.testsuite.admin.ApiUtil.resetUserPassword; + +public abstract class AbstractBrokerTest extends AbstractKeycloakTest { + + protected abstract RealmRepresentation createProviderRealm(); + protected abstract RealmRepresentation createConsumerRealm(); + + protected abstract List createProviderClients(); + protected abstract List createConsumerClients(); + + protected abstract IdentityProviderRepresentation setUpIdentityProvider(); + + protected abstract String providerRealmName(); + protected abstract String consumerRealmName(); + + protected abstract String getUserLogin(); + protected abstract String getUserPassword(); + protected abstract String getUserEmail(); + + protected abstract String getIDPAlias(); + + @Page + protected LoginPage accountLoginPage; + @Page + protected UpdateAccountInformationPage updateAccountInformationPage; + + @Override + public void addTestRealms(List testRealms) { + RealmRepresentation providerRealm = createProviderRealm(); + RealmRepresentation consumerRealm = createConsumerRealm(); + + testRealms.add(providerRealm); + testRealms.add(consumerRealm); + } + + @Before + public void createUser() { + log.debug("creating user for realm " + providerRealmName()); + + UserRepresentation user = new UserRepresentation(); + user.setUsername(getUserLogin()); + user.setEmail(getUserEmail()); + user.setEmailVerified(true); + user.setEnabled(true); + + RealmResource realmResource = adminClient.realm(providerRealmName()); + String userId = createUserWithAdminClient(realmResource, user); + + resetUserPassword(realmResource.users().get(userId), getUserPassword(), false); + } + + @Before + public void addIdentityProviderToProviderRealm() { + log.debug("adding identity provider to realm " + consumerRealmName()); + + RealmResource realm = adminClient.realm(consumerRealmName()); + realm.identityProviders().create(setUpIdentityProvider()); + } + + @Before + public void addClients() { + List clients = createProviderClients(); + if (clients != null) { + RealmResource providerRealm = adminClient.realm(providerRealmName()); + for (ClientRepresentation client : clients) { + log.debug("adding client " + client.getName() + " to realm " + providerRealmName()); + + providerRealm.clients().create(client); + } + } + + clients = createConsumerClients(); + if (clients != null) { + RealmResource consumerRealm = adminClient.realm(consumerRealmName()); + for (ClientRepresentation client : clients) { + log.debug("adding client " + client.getName() + " to realm " + consumerRealmName()); + + consumerRealm.clients().create(client); + } + } + } + + protected String getAuthRoot() { + return suiteContext.getAuthServerInfo().getContextRoot().toString(); + } + + protected IdentityProviderRepresentation createIdentityProvider(String alias, String providerId) { + IdentityProviderRepresentation identityProviderRepresentation = new IdentityProviderRepresentation(); + + identityProviderRepresentation.setAlias(alias); + identityProviderRepresentation.setProviderId(providerId); + identityProviderRepresentation.setEnabled(true); + + return identityProviderRepresentation; + } + + @Test + public void logInAsUserInIDP() { + driver.navigate().to(getAuthRoot() + "/auth/realms/" + consumerRealmName() + "/account"); + + log.debug("Clicking social " + getIDPAlias()); + accountLoginPage.clickSocial(getIDPAlias()); + + Assert.assertTrue("Driver should be on the provider realm page right now", + driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName() + "/")); + + log.debug("Logging in"); + accountLoginPage.login(getUserLogin(), getUserPassword()); + + Assert.assertTrue("We must be on update user profile page right now", + updateAccountInformationPage.isCurrent()); + + Assert.assertTrue("We must be on correct realm right now", + driver.getCurrentUrl().contains("/auth/realms/" + consumerRealmName() + "/")); + + log.debug("Updating info on updateAccount page"); + updateAccountInformationPage.updateAccountInformation("Firstname", "Lastname"); + + UsersResource consumerUsers = adminClient.realm(consumerRealmName()).users(); + Assert.assertTrue("There must be at least one user", consumerUsers.count() > 0); + + List users = consumerUsers.search("", 0, 5); + + boolean isUserFound = false; + for (UserRepresentation user : users) { + if (user.getUsername().equals(getUserLogin()) && user.getEmail().equals(getUserEmail())) { + isUserFound = true; + break; + } + } + + Assert.assertTrue("There must be user " + getUserLogin() + " in realm " + consumerRealmName(), + isUserFound); + + testSingleLogout(); + } + + protected void testSingleLogout() { + log.debug("Testing single log out"); + + driver.navigate().to(getAuthRoot() + "/auth/realms/" + providerRealmName() + "/account"); + + Assert.assertTrue("Should be logged in the account page", driver.getTitle().endsWith("Account Management")); + + driver.navigate().to(getAuthRoot() + + "/auth/realms/" + providerRealmName() + + "/protocol/" + "openid-connect" + + "/logout"); + + driver.navigate().to(getAuthRoot() + "/auth/realms/" + providerRealmName() + "/account"); + + Assert.assertTrue("Should be on login page", driver.getTitle().startsWith("Log in to")); + Assert.assertTrue("Should be on " + providerRealmName() + " realm", driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName())); + + driver.navigate().to(getAuthRoot() + "/auth/realms/" + consumerRealmName() + "/account"); + + Assert.assertTrue("Should be on login page", driver.getTitle().startsWith("Log in to")); + Assert.assertTrue("Should be on " + consumerRealmName() + " realm", driver.getCurrentUrl().contains("/auth/realms/" + consumerRealmName())); + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerTest.java new file mode 100644 index 0000000000..24ef5960e1 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerTest.java @@ -0,0 +1,104 @@ +package org.keycloak.testsuite.broker; + +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.keycloak.testsuite.broker.BrokerTestConstants.*; + +public class KcOidcBrokerTest extends AbstractBrokerTest { + + @Override + protected RealmRepresentation createProviderRealm() { + RealmRepresentation realm = new RealmRepresentation(); + realm.setRealm(REALM_PROV_NAME); + realm.setEnabled(true); + + return realm; + } + + @Override + protected RealmRepresentation createConsumerRealm() { + RealmRepresentation realm = new RealmRepresentation(); + realm.setRealm(REALM_CONS_NAME); + realm.setEnabled(true); + + return realm; + } + + @Override + protected List createProviderClients() { + ClientRepresentation client = new ClientRepresentation(); + client.setId(CLIENT_ID); + client.setName(CLIENT_ID); + client.setSecret(CLIENT_SECRET); + client.setEnabled(true); + + client.setRedirectUris(Collections.singletonList(getAuthRoot() + + "/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_OIDC_ALIAS + "/endpoint/*")); + + client.setAdminUrl(getAuthRoot() + + "/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_OIDC_ALIAS + "/endpoint"); + + return Collections.singletonList(client); + } + + @Override + protected List createConsumerClients() { + return null; + } + + @Override + protected IdentityProviderRepresentation setUpIdentityProvider() { + IdentityProviderRepresentation idp = createIdentityProvider(IDP_OIDC_ALIAS, IDP_OIDC_PROVIDER_ID); + + Map config = idp.getConfig(); + + config.put("clientId", CLIENT_ID); + config.put("clientSecret", CLIENT_SECRET); + config.put("prompt", "login"); + config.put("authorizationUrl", getAuthRoot() + "/auth/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/auth"); + config.put("tokenUrl", getAuthRoot() + "/auth/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/token"); + config.put("logoutUrl", getAuthRoot() + "/auth/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/logout"); + config.put("userInfoUrl", getAuthRoot() + "/auth/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/userinfo"); + config.put("defaultScope", "email profile"); + config.put("backchannelSupported", "true"); + + return idp; + } + + @Override + protected String getUserLogin() { + return USER_LOGIN; + } + + @Override + protected String getUserPassword() { + return USER_PASSWORD; + } + + @Override + protected String getUserEmail() { + return USER_EMAIL; + } + + @Override + protected String providerRealmName() { + return REALM_PROV_NAME; + } + + @Override + protected String consumerRealmName() { + return REALM_CONS_NAME; + } + + @Override + protected String getIDPAlias() { + return IDP_OIDC_ALIAS; + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlBrokerTest.java new file mode 100644 index 0000000000..cdacaa7874 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlBrokerTest.java @@ -0,0 +1,140 @@ +package org.keycloak.testsuite.broker; + +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.keycloak.testsuite.broker.BrokerTestConstants.*; + +public class KcSamlBrokerTest extends AbstractBrokerTest { + + @Override + protected RealmRepresentation createProviderRealm() { + RealmRepresentation realm = new RealmRepresentation(); + + realm.setEnabled(true); + realm.setRealm(REALM_PROV_NAME); + + return realm; + } + + @Override + protected RealmRepresentation createConsumerRealm() { + RealmRepresentation realm = new RealmRepresentation(); + + realm.setEnabled(true); + realm.setRealm(REALM_CONS_NAME); + + return realm; + } + + @Override + protected List createProviderClients() { + ClientRepresentation client = new ClientRepresentation(); + + client.setClientId(getAuthRoot() + "/auth/realms/" + REALM_CONS_NAME); + client.setEnabled(true); + client.setProtocol(IDP_SAML_PROVIDER_ID); + client.setRedirectUris(Collections.singletonList( + getAuthRoot() + "/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_SAML_ALIAS + "/endpoint" + )); + + Map attributes = new HashMap<>(); + + attributes.put("saml.authnstatement", "true"); + attributes.put("saml_single_logout_service_url_post", + getAuthRoot() + "/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_SAML_ALIAS + "/endpoint"); + attributes.put("saml_assertion_consumer_url_post", + getAuthRoot() + "/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"); + + client.setAttributes(attributes); + + ProtocolMapperRepresentation mapper = new ProtocolMapperRepresentation(); + mapper.setName("email"); + mapper.setProtocol("saml"); + mapper.setProtocolMapper("saml-user-property-mapper"); + mapper.setConsentRequired(false); + + Map mapperConfig = mapper.getConfig(); + mapperConfig.put("user.attribute", "email"); + mapperConfig.put("attribute.name", "urn:oid:1.2.840.113549.1.9.1"); + mapperConfig.put("attribute.nameformat", "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"); + mapperConfig.put("friendly.name", "email"); + + client.setProtocolMappers(Collections.singletonList( + mapper + )); + + return Collections.singletonList(client); + } + + @Override + protected List createConsumerClients() { + return null; + } + + @Override + protected IdentityProviderRepresentation setUpIdentityProvider() { + IdentityProviderRepresentation idp = createIdentityProvider(IDP_SAML_ALIAS, IDP_SAML_PROVIDER_ID); + + idp.setTrustEmail(true); + idp.setAddReadTokenRoleOnCreate(true); + idp.setStoreToken(true); + + Map config = idp.getConfig(); + + config.put("singleSignOnServiceUrl", getAuthRoot() + "/auth/realms/" + REALM_PROV_NAME + "/protocol/saml"); + config.put("singleLogoutServiceUrl", getAuthRoot() + "/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"); + + return idp; + } + + @Override + protected String providerRealmName() { + return REALM_PROV_NAME; + } + + @Override + protected String consumerRealmName() { + return REALM_CONS_NAME; + } + + @Override + protected String getUserLogin() { + return USER_LOGIN; + } + + @Override + protected String getUserPassword() { + return USER_PASSWORD; + } + + @Override + protected String getUserEmail() { + return USER_EMAIL; + } + + @Override + protected String getIDPAlias() { + return IDP_SAML_ALIAS; + } +} 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 new file mode 100644 index 0000000000..128d1e020e --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java @@ -0,0 +1,72 @@ +package org.keycloak.testsuite.broker; + +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.keycloak.testsuite.broker.BrokerTestConstants.*; + +public class KcSamlSignedBrokerTest extends KcSamlBrokerTest { + + @Override + protected RealmRepresentation createProviderRealm() { + RealmRepresentation realm = super.createProviderRealm(); + + realm.setPublicKey(REALM_PUBLIC_KEY); + realm.setPrivateKey(REALM_PRIVATE_KEY); + + return realm; + } + + @Override + protected RealmRepresentation createConsumerRealm() { + RealmRepresentation realm = super.createConsumerRealm(); + + realm.setPublicKey(REALM_PUBLIC_KEY); + realm.setPrivateKey(REALM_PRIVATE_KEY); + + return realm; + } + + @Override + protected List createProviderClients() { + List clientRepresentationList = super.createProviderClients(); + + 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", "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); + } + + return clientRepresentationList; + } + + @Override + protected IdentityProviderRepresentation setUpIdentityProvider() { + IdentityProviderRepresentation result = super.setUpIdentityProvider(); + + Map config = result.getConfig(); + + config.put("validateSignature", "true"); + config.put("wantAuthnRequestsSigned", "true"); + config.put("signingCertificate", IDP_SAML_SIGN_CERT); + + return result; + } +}