Merge pull request #3537 from hmlnarik/KEYCLOAK-3035

KEYCLOAK-3035 - Fix intermittent failures and refactor broker test
This commit is contained in:
Marek Posolda 2016-11-23 10:48:38 +01:00 committed by GitHub
commit 8ee2134e05
9 changed files with 603 additions and 452 deletions

View file

@ -0,0 +1,46 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Retry {
public static void execute(Runnable runnable, int retryCount, long intervalMillis) {
while (true) {
try {
runnable.run();
return;
} catch (RuntimeException e) {
retryCount--;
if (retryCount > 0) {
try {
Thread.sleep(intervalMillis);
} catch (InterruptedException ie) {
ie.addSuppressed(e);
throw new RuntimeException(ie);
}
} else {
throw e;
}
}
}
}
}

View file

@ -6,25 +6,19 @@ 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.Retry;
import org.keycloak.testsuite.pages.AccountPasswordPage;
import org.keycloak.testsuite.pages.ErrorPage;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.UpdateAccountInformationPage;
import org.keycloak.testsuite.util.RealmBuilder;
import org.openqa.selenium.By;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.openqa.selenium.TimeoutException;
import java.util.List;
import static org.junit.Assert.assertEquals;
@ -32,6 +26,7 @@ import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient;
import static org.keycloak.testsuite.admin.ApiUtil.resetUserPassword;
import static org.keycloak.testsuite.broker.BrokerTestConstants.USER_EMAIL;
import static org.keycloak.testsuite.broker.BrokerTestTools.*;
import org.keycloak.testsuite.pages.IdpConfirmLinkPage;
import static org.keycloak.testsuite.util.MailAssert.assertEmailAndGetUrl;
import org.keycloak.testsuite.util.MailServer;
@ -40,23 +35,6 @@ import org.keycloak.testsuite.util.UserBuilder;
public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
protected abstract RealmRepresentation createProviderRealm();
protected abstract RealmRepresentation createConsumerRealm();
protected abstract List<ClientRepresentation> createProviderClients();
protected abstract List<ClientRepresentation> 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;
@ -72,10 +50,18 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
@Page
protected IdpConfirmLinkPage idpConfirmLinkPage;
protected BrokerConfiguration bc = getBrokerConfiguration();
/**
* Returns a broker configuration. Return value should not change between calls.
* @return
*/
protected abstract BrokerConfiguration getBrokerConfiguration();
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation providerRealm = createProviderRealm();
RealmRepresentation consumerRealm = createConsumerRealm();
RealmRepresentation providerRealm = bc.createProviderRealm();
RealmRepresentation consumerRealm = bc.createConsumerRealm();
testRealms.add(providerRealm);
testRealms.add(consumerRealm);
@ -83,45 +69,45 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
@Before
public void createUser() {
log.debug("creating user for realm " + providerRealmName());
log.debug("creating user for realm " + bc.providerRealmName());
UserRepresentation user = new UserRepresentation();
user.setUsername(getUserLogin());
user.setEmail(getUserEmail());
user.setUsername(bc.getUserLogin());
user.setEmail(bc.getUserEmail());
user.setEmailVerified(true);
user.setEnabled(true);
RealmResource realmResource = adminClient.realm(providerRealmName());
RealmResource realmResource = adminClient.realm(bc.providerRealmName());
String userId = createUserWithAdminClient(realmResource, user);
resetUserPassword(realmResource.users().get(userId), getUserPassword(), false);
resetUserPassword(realmResource.users().get(userId), bc.getUserPassword(), false);
}
@Before
public void addIdentityProviderToProviderRealm() {
log.debug("adding identity provider to realm " + consumerRealmName());
log.debug("adding identity provider to realm " + bc.consumerRealmName());
RealmResource realm = adminClient.realm(consumerRealmName());
realm.identityProviders().create(setUpIdentityProvider());
RealmResource realm = adminClient.realm(bc.consumerRealmName());
realm.identityProviders().create(bc.setUpIdentityProvider(suiteContext));
}
@Before
public void addClients() {
List<ClientRepresentation> clients = createProviderClients();
List<ClientRepresentation> clients = bc.createProviderClients(suiteContext);
if (clients != null) {
RealmResource providerRealm = adminClient.realm(providerRealmName());
RealmResource providerRealm = adminClient.realm(bc.providerRealmName());
for (ClientRepresentation client : clients) {
log.debug("adding client " + client.getName() + " to realm " + providerRealmName());
log.debug("adding client " + client.getName() + " to realm " + bc.providerRealmName());
providerRealm.clients().create(client);
}
}
clients = createConsumerClients();
clients = bc.createConsumerClients(suiteContext);
if (clients != null) {
RealmResource consumerRealm = adminClient.realm(consumerRealmName());
RealmResource consumerRealm = adminClient.realm(bc.consumerRealmName());
for (ClientRepresentation client : clients) {
log.debug("adding client " + client.getName() + " to realm " + consumerRealmName());
log.debug("adding client " + client.getName() + " to realm " + bc.consumerRealmName());
consumerRealm.clients().create(client);
}
@ -132,42 +118,31 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
return suiteContext.getAuthServerInfo().getContextRoot().toString();
}
protected IdentityProviderRepresentation createIdentityProvider(String alias, String providerId) {
IdentityProviderRepresentation identityProviderRepresentation = new IdentityProviderRepresentation();
identityProviderRepresentation.setAlias(alias);
identityProviderRepresentation.setDisplayName(providerId);
identityProviderRepresentation.setProviderId(providerId);
identityProviderRepresentation.setEnabled(true);
return identityProviderRepresentation;
}
@Test
public void logInAsUserInIDP() {
driver.navigate().to(getAccountUrl(consumerRealmName()));
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
log.debug("Clicking social " + getIDPAlias());
accountLoginPage.clickSocial(getIDPAlias());
log.debug("Clicking social " + bc.getIDPAlias());
accountLoginPage.clickSocial(bc.getIDPAlias());
waitForPage("log in to");
waitForPage(driver, "log in to");
Assert.assertTrue("Driver should be on the provider realm page right now",
driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName() + "/"));
driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
log.debug("Logging in");
accountLoginPage.login(getUserLogin(), getUserPassword());
accountLoginPage.login(bc.getUserLogin(), bc.getUserPassword());
waitForPage("update account information");
waitForPage(driver, "update account information");
Assert.assertTrue(updateAccountInformationPage.isCurrent());
Assert.assertTrue("We must be on correct realm right now",
driver.getCurrentUrl().contains("/auth/realms/" + consumerRealmName() + "/"));
driver.getCurrentUrl().contains("/auth/realms/" + bc.consumerRealmName() + "/"));
log.debug("Updating info on updateAccount page");
updateAccountInformationPage.updateAccountInformation("Firstname", "Lastname");
UsersResource consumerUsers = adminClient.realm(consumerRealmName()).users();
UsersResource consumerUsers = adminClient.realm(bc.consumerRealmName()).users();
int userCount = consumerUsers.count();
Assert.assertTrue("There must be at least one user", userCount > 0);
@ -176,13 +151,13 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
boolean isUserFound = false;
for (UserRepresentation user : users) {
if (user.getUsername().equals(getUserLogin()) && user.getEmail().equals(getUserEmail())) {
if (user.getUsername().equals(bc.getUserLogin()) && user.getEmail().equals(bc.getUserEmail())) {
isUserFound = true;
break;
}
}
Assert.assertTrue("There must be user " + getUserLogin() + " in realm " + consumerRealmName(),
Assert.assertTrue("There must be user " + bc.getUserLogin() + " in realm " + bc.consumerRealmName(),
isUserFound);
testSingleLogout();
@ -192,22 +167,22 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
public void loginWithExistingUser() {
logInAsUserInIDP();
Integer userCount = adminClient.realm(consumerRealmName()).users().count();
Integer userCount = adminClient.realm(bc.consumerRealmName()).users().count();
driver.navigate().to(getAccountUrl(consumerRealmName()));
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
log.debug("Clicking social " + getIDPAlias());
accountLoginPage.clickSocial(getIDPAlias());
log.debug("Clicking social " + bc.getIDPAlias());
accountLoginPage.clickSocial(bc.getIDPAlias());
waitForPage("log in to");
waitForPage(driver, "log in to");
Assert.assertTrue("Driver should be on the provider realm page right now", driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName() + "/"));
Assert.assertTrue("Driver should be on the provider realm page right now", driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
accountLoginPage.login(getUserLogin(), getUserPassword());
accountLoginPage.login(bc.getUserLogin(), bc.getUserPassword());
assertEquals(accountPage.buildUri().toASCIIString().replace("master", "consumer") + "/", driver.getCurrentUrl());
assertEquals(userCount, adminClient.realm(consumerRealmName()).users().count());
assertEquals(userCount, adminClient.realm(bc.consumerRealmName()).users().count());
}
// KEYCLOAK-2957
@ -219,40 +194,40 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
try {
//configure smpt server in the realm
RealmRepresentation master = adminClient.realm(consumerRealmName()).toRepresentation();
RealmRepresentation master = adminClient.realm(bc.consumerRealmName()).toRepresentation();
master.setSmtpServer(suiteContext.getSmtpServer());
adminClient.realm(consumerRealmName()).update(master);
adminClient.realm(bc.consumerRealmName()).update(master);
//create user on consumer's site who should be linked later
UserRepresentation newUser = UserBuilder.create().username("consumer").email(USER_EMAIL).enabled(true).build();
String userId = createUserWithAdminClient(adminClient.realm(consumerRealmName()), newUser);
resetUserPassword(adminClient.realm(consumerRealmName()).users().get(userId), "password", false);
String userId = createUserWithAdminClient(adminClient.realm(bc.consumerRealmName()), newUser);
resetUserPassword(adminClient.realm(bc.consumerRealmName()).users().get(userId), "password", false);
//test
driver.navigate().to(getAccountUrl(consumerRealmName()));
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
log.debug("Clicking social " + getIDPAlias());
accountLoginPage.clickSocial(getIDPAlias());
log.debug("Clicking social " + bc.getIDPAlias());
accountLoginPage.clickSocial(bc.getIDPAlias());
waitForPage("log in to");
waitForPage(driver, "log in to");
Assert.assertTrue("Driver should be on the provider realm page right now",
driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName() + "/"));
driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
log.debug("Logging in");
accountLoginPage.login(getUserLogin(), getUserPassword());
accountLoginPage.login(bc.getUserLogin(), bc.getUserPassword());
waitForPage("update account information");
waitForPage(driver, "update account information");
Assert.assertTrue(updateAccountInformationPage.isCurrent());
Assert.assertTrue("We must be on correct realm right now",
driver.getCurrentUrl().contains("/auth/realms/" + consumerRealmName() + "/"));
driver.getCurrentUrl().contains("/auth/realms/" + bc.consumerRealmName() + "/"));
log.debug("Updating info on updateAccount page");
updateAccountInformationPage.updateAccountInformation("Firstname", "Lastname");
//link account by email
waitForPage("account already exists");
waitForPage(driver, "account already exists");
idpConfirmLinkPage.clickLinkAccount();
String url = assertEmailAndGetUrl(MailServerConfiguration.FROM, USER_EMAIL,
@ -265,7 +240,7 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
assertEquals(accountPage.buildUri().toASCIIString().replace("master", "consumer") + "/", driver.getCurrentUrl());
//test if the user has verified email
assertTrue(adminClient.realm(consumerRealmName()).users().get(userId).toRepresentation().isEmailVerified());
assertTrue(adminClient.realm(bc.consumerRealmName()).users().get(userId).toRepresentation().isEmailVerified());
} finally {
// stop mail server
MailServer.stop();
@ -275,23 +250,20 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
// KEYCLOAK-3267
@Test
public void loginWithExistingUserWithBruteForceEnabled() {
adminClient.realm(consumerRealmName()).update(RealmBuilder.create().bruteForceProtected(true).failureFactor(2).build());
adminClient.realm(bc.consumerRealmName()).update(RealmBuilder.create().bruteForceProtected(true).failureFactor(2).build());
loginWithExistingUser();
driver.navigate().to(getAccountPasswordUrl(consumerRealmName()));
driver.navigate().to(getAccountPasswordUrl(bc.consumerRealmName()));
accountPasswordPage.changePassword("password", "password");
driver.navigate().to(getAuthRoot()
+ "/auth/realms/" + providerRealmName()
+ "/protocol/" + "openid-connect"
+ "/logout?redirect_uri=" + encodeUrl(getAccountUrl(providerRealmName())));
logoutFromRealm(bc.providerRealmName());
driver.navigate().to(getAccountUrl(consumerRealmName()));
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
try {
waitForPage("log in to");
waitForPage(driver, "log in to");
} catch (TimeoutException e) {
log.debug(driver.getTitle());
log.debug(driver.getPageSource());
@ -300,53 +272,71 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
for (int i = 0; i < 3; i++) {
try {
waitForElementEnabled("login");
waitForElementEnabled(driver, "login");
} catch (TimeoutException e) {
Assert.fail("Timeout while waiting for login element enabled");
}
accountLoginPage.login(getUserLogin(), "invalid");
accountLoginPage.login(bc.getUserLogin(), "invalid");
}
assertEquals("Invalid username or password.", accountLoginPage.getError());
accountLoginPage.clickSocial(getIDPAlias());
accountLoginPage.clickSocial(bc.getIDPAlias());
try {
waitForPage("log in to");
waitForPage(driver, "log in to");
} catch (TimeoutException e) {
log.debug(driver.getTitle());
log.debug(driver.getPageSource());
Assert.fail("Timeout while waiting for login page");
}
Assert.assertTrue("Driver should be on the provider realm page right now", driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName() + "/"));
Assert.assertTrue("Driver should be on the provider realm page right now", driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
accountLoginPage.login(getUserLogin(), getUserPassword());
accountLoginPage.login(bc.getUserLogin(), bc.getUserPassword());
assertEquals("Account is disabled, contact admin.", errorPage.getError());
}
private void testSingleLogout() {
protected void logoutFromRealm(String realm) {
driver.navigate().to(getAuthRoot()
+ "/auth/realms/" + realm
+ "/protocol/" + "openid-connect"
+ "/logout?redirect_uri=" + encodeUrl(getAccountUrl(realm)));
try {
Retry.execute(() -> {
try {
waitForPage(driver, "log in to " + realm);
} catch (TimeoutException ex) {
driver.navigate().refresh();
log.debug("[Retriable] Timed out waiting for login page");
throw ex;
}
}, 10, 100);
} catch (TimeoutException e) {
log.debug(driver.getTitle());
log.debug(driver.getPageSource());
Assert.fail("Timeout while waiting for login page");
}
}
protected void testSingleLogout() {
log.debug("Testing single log out");
driver.navigate().to(getAccountUrl(providerRealmName()));
driver.navigate().to(getAccountUrl(bc.providerRealmName()));
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?redirect_uri=" + encodeUrl(getAccountUrl(providerRealmName())));
logoutFromRealm(bc.providerRealmName());
waitForPage("log in to " + providerRealmName());
Assert.assertTrue("Should be on " + bc.providerRealmName() + " realm", driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName()));
Assert.assertTrue("Should be on " + providerRealmName() + " realm", driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName()));
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
driver.navigate().to(getAccountUrl(consumerRealmName()));
Assert.assertTrue("Should be on " + consumerRealmName() + " realm on login page",
driver.getCurrentUrl().contains("/auth/realms/" + consumerRealmName() + "/protocol/openid-connect/"));
Assert.assertTrue("Should be on " + bc.consumerRealmName() + " realm on login page",
driver.getCurrentUrl().contains("/auth/realms/" + bc.consumerRealmName() + "/protocol/openid-connect/"));
}
private String getAccountUrl(String realmName) {
@ -356,45 +346,4 @@ public abstract class AbstractBrokerTest extends AbstractKeycloakTest {
private String getAccountPasswordUrl(String realmName) {
return getAuthRoot() + "/auth/realms/" + realmName + "/account/password";
}
private void waitForPage(final String title) {
WebDriverWait wait = new WebDriverWait(driver, 5);
ExpectedCondition<Boolean> condition = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver input) {
return input.getTitle().toLowerCase().contains(title);
}
};
wait.until(condition);
}
private void waitForElementEnabled(final String elementName) {
WebDriverWait wait = new WebDriverWait(driver, 5);
ExpectedCondition<Boolean> condition = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver input) {
List<WebElement> elements = input.findElements(By.name(elementName));
if (elements.size() == 0)
return false;
return elements.get(0).isEnabled();
}
};
wait.until(condition);
}
private String encodeUrl(String url) {
String result;
try {
result = URLEncoder.encode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
result = url;
}
return result;
}
}

View file

@ -0,0 +1,64 @@
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.List;
/**
*
* @author hmlnarik
*/
public interface BrokerConfiguration {
/**
* @return Representation of the realm at the identity provider side.
*/
RealmRepresentation createProviderRealm();
/**
* @return Representation of the realm at the broker side.
*/
RealmRepresentation createConsumerRealm();
List<ClientRepresentation> createProviderClients(SuiteContext suiteContext);
List<ClientRepresentation> createConsumerClients(SuiteContext suiteContext);
/**
* @return Representation of the identity provider for declaration in the broker
*/
IdentityProviderRepresentation setUpIdentityProvider(SuiteContext suiteContext);
/**
* @return Name of realm containing identity provider. Must be consistent with {@link #createProviderRealm()}
*/
String providerRealmName();
/**
* @return Realm name of the broker. Must be consistent with {@link #createConsumerRealm()}
*/
String consumerRealmName();
/**
* @return User login name of the brokered user
*/
String getUserLogin();
/**
* @return Password of the brokered user
*/
String getUserPassword();
/**
* @return E-mail of the brokered user
*/
String getUserEmail();
/**
* @return Alias of the identity provider as defined in the broker realm
*/
String getIDPAlias();
}

View file

@ -0,0 +1,65 @@
package org.keycloak.testsuite.broker;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.testsuite.arquillian.SuiteContext;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
/**
*
* @author hmlnarik
*/
public class BrokerTestTools {
public static String getAuthRoot(SuiteContext suiteContext) {
return suiteContext.getAuthServerInfo().getContextRoot().toString();
}
public static IdentityProviderRepresentation createIdentityProvider(String alias, String providerId) {
IdentityProviderRepresentation identityProviderRepresentation = new IdentityProviderRepresentation();
identityProviderRepresentation.setAlias(alias);
identityProviderRepresentation.setDisplayName(providerId);
identityProviderRepresentation.setProviderId(providerId);
identityProviderRepresentation.setEnabled(true);
return identityProviderRepresentation;
}
public static void waitForPage(WebDriver driver, final String title) {
WebDriverWait wait = new WebDriverWait(driver, 5);
ExpectedCondition<Boolean> condition = (WebDriver input) -> input.getTitle().toLowerCase().contains(title);
wait.until(condition);
}
public static void waitForElementEnabled(WebDriver driver, final String elementName) {
WebDriverWait wait = new WebDriverWait(driver, 5);
ExpectedCondition<Boolean> condition = (WebDriver input) -> {
List<WebElement> elements = input.findElements(By.name(elementName));
return (! elements.isEmpty()) && elements.get(0).isEnabled();
};
wait.until(condition);
}
public static String encodeUrl(String url) {
String result;
try {
result = URLEncoder.encode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
result = url;
}
return result;
}
}

View file

@ -0,0 +1,112 @@
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.Collections;
import java.util.List;
import java.util.Map;
import static org.keycloak.testsuite.broker.BrokerTestConstants.*;
import static org.keycloak.testsuite.broker.BrokerTestTools.*;
/**
*
* @author hmlnarik
*/
public class KcOidcBrokerConfiguration implements BrokerConfiguration {
public static final KcOidcBrokerConfiguration INSTANCE = new KcOidcBrokerConfiguration();
@Override
public RealmRepresentation createProviderRealm() {
RealmRepresentation realm = new RealmRepresentation();
realm.setRealm(REALM_PROV_NAME);
realm.setEnabled(true);
return realm;
}
@Override
public RealmRepresentation createConsumerRealm() {
RealmRepresentation realm = new RealmRepresentation();
realm.setRealm(REALM_CONS_NAME);
realm.setEnabled(true);
return realm;
}
@Override
public List<ClientRepresentation> createProviderClients(SuiteContext suiteContext) {
ClientRepresentation client = new ClientRepresentation();
client.setId(CLIENT_ID);
client.setName(CLIENT_ID);
client.setSecret(CLIENT_SECRET);
client.setEnabled(true);
client.setRedirectUris(Collections.singletonList(getAuthRoot(suiteContext) +
"/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_OIDC_ALIAS + "/endpoint/*"));
client.setAdminUrl(getAuthRoot(suiteContext) +
"/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_OIDC_ALIAS + "/endpoint");
return Collections.singletonList(client);
}
@Override
public List<ClientRepresentation> createConsumerClients(SuiteContext suiteContext) {
return null;
}
@Override
public IdentityProviderRepresentation setUpIdentityProvider(SuiteContext suiteContext) {
IdentityProviderRepresentation idp = createIdentityProvider(IDP_OIDC_ALIAS, IDP_OIDC_PROVIDER_ID);
Map<String, String> config = idp.getConfig();
config.put("clientId", CLIENT_ID);
config.put("clientSecret", CLIENT_SECRET);
config.put("prompt", "login");
config.put("authorizationUrl", getAuthRoot(suiteContext) + "/auth/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/auth");
config.put("tokenUrl", getAuthRoot(suiteContext) + "/auth/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/token");
config.put("logoutUrl", getAuthRoot(suiteContext) + "/auth/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/logout");
config.put("userInfoUrl", getAuthRoot(suiteContext) + "/auth/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/userinfo");
config.put("defaultScope", "email profile");
config.put("backchannelSupported", "true");
return idp;
}
@Override
public String getUserLogin() {
return USER_LOGIN;
}
@Override
public String getUserPassword() {
return USER_PASSWORD;
}
@Override
public String getUserEmail() {
return USER_EMAIL;
}
@Override
public String providerRealmName() {
return REALM_PROV_NAME;
}
@Override
public String consumerRealmName() {
return REALM_CONS_NAME;
}
@Override
public String getIDPAlias() {
return IDP_OIDC_ALIAS;
}
}

View file

@ -1,112 +1,9 @@
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.CLIENT_ID;
import static org.keycloak.testsuite.broker.BrokerTestConstants.CLIENT_SECRET;
import static org.keycloak.testsuite.broker.BrokerTestConstants.IDP_OIDC_ALIAS;
import static org.keycloak.testsuite.broker.BrokerTestConstants.IDP_OIDC_PROVIDER_ID;
import static org.keycloak.testsuite.broker.BrokerTestConstants.REALM_CONS_NAME;
import static org.keycloak.testsuite.broker.BrokerTestConstants.REALM_PROV_NAME;
import static org.keycloak.testsuite.broker.BrokerTestConstants.USER_EMAIL;
import static org.keycloak.testsuite.broker.BrokerTestConstants.USER_LOGIN;
import static org.keycloak.testsuite.broker.BrokerTestConstants.USER_PASSWORD;
public class KcOidcBrokerTest extends AbstractBrokerTest {
@Override
protected RealmRepresentation createProviderRealm() {
RealmRepresentation realm = new RealmRepresentation();
realm.setRealm(REALM_PROV_NAME);
realm.setEnabled(true);
return realm;
protected BrokerConfiguration getBrokerConfiguration() {
return KcOidcBrokerConfiguration.INSTANCE;
}
@Override
protected RealmRepresentation createConsumerRealm() {
RealmRepresentation realm = new RealmRepresentation();
realm.setRealm(REALM_CONS_NAME);
realm.setEnabled(true);
return realm;
}
@Override
protected List<ClientRepresentation> 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<ClientRepresentation> createConsumerClients() {
return null;
}
@Override
protected IdentityProviderRepresentation setUpIdentityProvider() {
IdentityProviderRepresentation idp = createIdentityProvider(IDP_OIDC_ALIAS, IDP_OIDC_PROVIDER_ID);
Map<String, String> 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;
}
}

View file

@ -0,0 +1,150 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
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 org.keycloak.testsuite.arquillian.SuiteContext;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.keycloak.testsuite.broker.BrokerTestConstants.*;
import static org.keycloak.testsuite.broker.BrokerTestTools.*;
public class KcSamlBrokerConfiguration implements BrokerConfiguration {
public static final KcSamlBrokerConfiguration INSTANCE = new KcSamlBrokerConfiguration();
@Override
public RealmRepresentation createProviderRealm() {
RealmRepresentation realm = new RealmRepresentation();
realm.setEnabled(true);
realm.setRealm(REALM_PROV_NAME);
return realm;
}
@Override
public RealmRepresentation createConsumerRealm() {
RealmRepresentation realm = new RealmRepresentation();
realm.setEnabled(true);
realm.setRealm(REALM_CONS_NAME);
return realm;
}
@Override
public List<ClientRepresentation> createProviderClients(SuiteContext suiteContext) {
ClientRepresentation client = new ClientRepresentation();
client.setClientId(getAuthRoot(suiteContext) + "/auth/realms/" + REALM_CONS_NAME);
client.setEnabled(true);
client.setProtocol(IDP_SAML_PROVIDER_ID);
client.setRedirectUris(Collections.singletonList(
getAuthRoot(suiteContext) + "/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_SAML_ALIAS + "/endpoint"
));
Map<String, String> attributes = new HashMap<>();
attributes.put("saml.authnstatement", "true");
attributes.put("saml_single_logout_service_url_post",
getAuthRoot(suiteContext) + "/auth/realms/" + REALM_CONS_NAME + "/broker/" + IDP_SAML_ALIAS + "/endpoint");
attributes.put("saml_assertion_consumer_url_post",
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");
client.setAttributes(attributes);
ProtocolMapperRepresentation mapper = new ProtocolMapperRepresentation();
mapper.setName("email");
mapper.setProtocol("saml");
mapper.setProtocolMapper("saml-user-property-mapper");
mapper.setConsentRequired(false);
Map<String, String> 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
public List<ClientRepresentation> createConsumerClients(SuiteContext suiteContext) {
return null;
}
@Override
public IdentityProviderRepresentation setUpIdentityProvider(SuiteContext suiteContext) {
IdentityProviderRepresentation idp = createIdentityProvider(IDP_SAML_ALIAS, IDP_SAML_PROVIDER_ID);
idp.setTrustEmail(true);
idp.setAddReadTokenRoleOnCreate(true);
idp.setStoreToken(true);
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");
return idp;
}
@Override
public String providerRealmName() {
return REALM_PROV_NAME;
}
@Override
public String consumerRealmName() {
return REALM_CONS_NAME;
}
@Override
public String getUserLogin() {
return USER_LOGIN;
}
@Override
public String getUserPassword() {
return USER_PASSWORD;
}
@Override
public String getUserEmail() {
return USER_EMAIL;
}
@Override
public String getIDPAlias() {
return IDP_SAML_ALIAS;
}
}

View file

@ -1,148 +1,9 @@
package org.keycloak.testsuite.broker;
import org.junit.Ignore;
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.IDP_SAML_ALIAS;
import static org.keycloak.testsuite.broker.BrokerTestConstants.IDP_SAML_PROVIDER_ID;
import static org.keycloak.testsuite.broker.BrokerTestConstants.REALM_CONS_NAME;
import static org.keycloak.testsuite.broker.BrokerTestConstants.REALM_PROV_NAME;
import static org.keycloak.testsuite.broker.BrokerTestConstants.USER_EMAIL;
import static org.keycloak.testsuite.broker.BrokerTestConstants.USER_LOGIN;
import static org.keycloak.testsuite.broker.BrokerTestConstants.USER_PASSWORD;
@Ignore
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<ClientRepresentation> 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<String, String> 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<String, String> 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<ClientRepresentation> 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<String, String> 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;
protected BrokerConfiguration getBrokerConfiguration() {
return KcSamlBrokerConfiguration.INSTANCE;
}
}

View file

@ -1,77 +1,84 @@
package org.keycloak.testsuite.broker;
import org.junit.Ignore;
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.IDP_SAML_SIGN_CERT;
import static org.keycloak.testsuite.broker.BrokerTestConstants.IDP_SAML_SIGN_KEY;
import static org.keycloak.testsuite.broker.BrokerTestConstants.REALM_PRIVATE_KEY;
import static org.keycloak.testsuite.broker.BrokerTestConstants.REALM_PUBLIC_KEY;
import static org.keycloak.testsuite.broker.BrokerTestConstants.*;
@Ignore
public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
@Override
protected RealmRepresentation createProviderRealm() {
RealmRepresentation realm = super.createProviderRealm();
public static class KcSamlSignedBrokerConfiguration extends KcSamlBrokerConfiguration {
realm.setPublicKey(REALM_PUBLIC_KEY);
realm.setPrivateKey(REALM_PRIVATE_KEY);
public static final KcSamlSignedBrokerConfiguration INSTANCE = new KcSamlSignedBrokerConfiguration();
return realm;
}
@Override
public RealmRepresentation createProviderRealm() {
RealmRepresentation realm = super.createProviderRealm();
@Override
protected RealmRepresentation createConsumerRealm() {
RealmRepresentation realm = super.createConsumerRealm();
realm.setPublicKey(REALM_PUBLIC_KEY);
realm.setPrivateKey(REALM_PRIVATE_KEY);
realm.setPublicKey(REALM_PUBLIC_KEY);
realm.setPrivateKey(REALM_PRIVATE_KEY);
return realm;
}
@Override
protected List<ClientRepresentation> createProviderClients() {
List<ClientRepresentation> clientRepresentationList = super.createProviderClients();
for (ClientRepresentation client : clientRepresentationList) {
client.setClientAuthenticatorType("client-secret");
client.setSurrogateAuthRequired(false);
Map<String, String> 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 realm;
}
return clientRepresentationList;
@Override
public RealmRepresentation createConsumerRealm() {
RealmRepresentation realm = super.createConsumerRealm();
realm.setPublicKey(REALM_PUBLIC_KEY);
realm.setPrivateKey(REALM_PRIVATE_KEY);
return realm;
}
@Override
public List<ClientRepresentation> createProviderClients(SuiteContext suiteContext) {
List<ClientRepresentation> clientRepresentationList = super.createProviderClients(suiteContext);
for (ClientRepresentation client : clientRepresentationList) {
client.setClientAuthenticatorType("client-secret");
client.setSurrogateAuthRequired(false);
Map<String, String> 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
public IdentityProviderRepresentation setUpIdentityProvider(SuiteContext suiteContext) {
IdentityProviderRepresentation result = super.setUpIdentityProvider(suiteContext);
Map<String, String> config = result.getConfig();
config.put("validateSignature", "true");
config.put("wantAuthnRequestsSigned", "true");
config.put("signingCertificate", IDP_SAML_SIGN_CERT);
return result;
}
}
@Override
protected IdentityProviderRepresentation setUpIdentityProvider() {
IdentityProviderRepresentation result = super.setUpIdentityProvider();
Map<String, String> config = result.getConfig();
config.put("validateSignature", "true");
config.put("wantAuthnRequestsSigned", "true");
config.put("signingCertificate", IDP_SAML_SIGN_CERT);
return result;
protected BrokerConfiguration getBrokerConfiguration() {
return KcSamlSignedBrokerConfiguration.INSTANCE;
}
}