Move ConsentsTest.java to the new testsuite (#40323)

* Moving files to the new test suite

Signed-off-by: Lukas Hanusovsky <lhanusov@redhat.com>

* Move ConsentsTest.java, UserRoleTest.java to the new testsuite

Part of: #34494

Signed-off-by: Lukas Hanusovsky <lhanusov@redhat.com>

---------

Signed-off-by: Lukas Hanusovsky <lhanusov@redhat.com>
This commit is contained in:
Lukas Hanusovsky 2025-07-22 12:31:59 +02:00 committed by GitHub
parent 7fd3380b19
commit d7273e6b1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 541 additions and 694 deletions

View file

@ -5,7 +5,6 @@ import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
public class ClientConfigBuilder {
@ -127,19 +126,22 @@ public class ClientConfigBuilder {
}
public ClientConfigBuilder defaultClientScopes(String... defaultClientScopes) {
if (rep.getDefaultClientScopes() == null) {
rep.setDefaultClientScopes(new LinkedList<>());
}
rep.getDefaultClientScopes().addAll(List.of(defaultClientScopes));
rep.setDefaultClientScopes(Collections.combine(rep.getDefaultClientScopes(), defaultClientScopes));
return this;
}
public ClientConfigBuilder protocolMappers(List<ProtocolMapperRepresentation> mappers) {
if (rep.getProtocolMappers() == null) {
rep.setProtocolMappers(new LinkedList<>());
}
rep.getProtocolMappers().addAll(mappers);
rep.setProtocolMappers(Collections.combine(rep.getProtocolMappers(), mappers));
return this;
}
public ClientConfigBuilder consentRequired(boolean enabled) {
rep.setConsentRequired(enabled);
return this;
}
public ClientConfigBuilder webOrigins(String... webOrigins) {
rep.setWebOrigins(Collections.combine(rep.getWebOrigins(), webOrigins));
return this;
}

View file

@ -2,6 +2,7 @@ package org.keycloak.testframework.realm;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RolesRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
@ -220,6 +221,11 @@ public class RealmConfigBuilder {
return this;
}
public RealmConfigBuilder identityProvider(IdentityProviderRepresentation identityProvider) {
rep.addIdentityProvider(identityProvider);
return this;
}
/**
* Best practice is to use other convenience methods when configuring a realm, but while the framework is under
* active development there may not be a way to perform all updates required. In these cases this method allows

View file

@ -0,0 +1,49 @@
/*
* 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.testframework.ui.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class ConsentPage extends AbstractPage {
@FindBy(id = "kc-login")
private WebElement submitButton;
@FindBy(id = "kc-cancel")
private WebElement cancelButton;
public ConsentPage(WebDriver driver) { super(driver); }
public void confirm() {
submitButton.click();
}
public void cancel() {
cancelButton.click();
}
@Override
public String getExpectedPageId() {
return "login-login-oauth-grant";
}
}

View file

@ -1,5 +1,6 @@
package org.keycloak.testframework.ui.page;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
@ -28,6 +29,16 @@ public class LoginPage extends AbstractPage {
submitButton.click();
}
public void clickSocial(String alias) {
WebElement socialButton = findSocialButton(alias);
socialButton.click();
}
public WebElement findSocialButton(String alias) {
String id = "social-" + alias;
return driver.findElement(By.id(id));
}
@Override
public String getExpectedPageId() {
return "login-login";

View file

@ -0,0 +1,463 @@
/*
* 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.tests.admin;
import org.jboss.logging.Logger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventType;
import org.keycloak.models.ClientModel;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.UserSessionRepresentation;
import org.keycloak.testframework.annotations.InjectClient;
import org.keycloak.testframework.annotations.InjectEvents;
import org.keycloak.testframework.annotations.InjectRealm;
import org.keycloak.testframework.annotations.InjectUser;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
import org.keycloak.testframework.events.Events;
import org.keycloak.testframework.injection.LifeCycle;
import org.keycloak.testframework.oauth.OAuthClient;
import org.keycloak.testframework.oauth.annotations.InjectOAuthClient;
import org.keycloak.testframework.realm.ClientConfig;
import org.keycloak.testframework.realm.ClientConfigBuilder;
import org.keycloak.testframework.realm.ManagedClient;
import org.keycloak.testframework.realm.ManagedRealm;
import org.keycloak.testframework.realm.ManagedUser;
import org.keycloak.testframework.realm.RealmConfig;
import org.keycloak.testframework.realm.RealmConfigBuilder;
import org.keycloak.testframework.realm.UserConfig;
import org.keycloak.testframework.realm.UserConfigBuilder;
import org.keycloak.testframework.ui.annotations.InjectPage;
import org.keycloak.testframework.ui.annotations.InjectWebDriver;
import org.keycloak.testframework.ui.page.ConsentPage;
import org.keycloak.testframework.ui.page.LoginPage;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.keycloak.tests.utils.admin.ApiUtil.findClientByClientId;
import org.keycloak.testsuite.util.AccountHelper;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
@KeycloakIntegrationTest
public class ConsentsTest {
@InjectRealm(ref = "user")
ManagedRealm userRealm;
@InjectRealm(ref = "consumer", config = ConsumerRealmConf.class, lifecycle = LifeCycle.METHOD)
ManagedRealm consumerRealm;
@InjectRealm(ref = "provider", lifecycle = LifeCycle.METHOD)
ManagedRealm providerRealm;
@InjectUser(ref = "user", realmRef = "user", config = UserRealmUserConf.class)
ManagedUser userFromUserRealm;
@InjectUser(ref = "provider", realmRef = "provider", config = ProviderRealmUserConf.class)
ManagedUser userFromProviderRealm;
@InjectClient(realmRef = "provider", config = ProviderRealmClientConf.class)
ManagedClient providerRealmClient;
@InjectOAuthClient(ref = "user", realmRef = "user")
OAuthClient userRealmOAuth;
@InjectOAuthClient(ref = "consumer", realmRef = "consumer")
OAuthClient consumerRealmOAuth;
@InjectOAuthClient(ref = "provider", realmRef = "provider")
OAuthClient providerRealmOAuth;
@InjectEvents(realmRef = "user")
Events userRealmEvents;
@InjectWebDriver
WebDriver driver;
@InjectPage
LoginPage loginPage;
@InjectPage
ConsentPage consentPage;
private static final Logger LOGGER = Logger.getLogger(ConsentsTest.class);
private static final String REALM_PROV_NAME = "provider";
private static final String REALM_CONS_NAME = "consumer";
private static final String IDP_OIDC_ALIAS = "kc-oidc-idp";
private static final String IDP_OIDC_PROVIDER_ID = "keycloak-oidc";
private static final String CLIENT_ID = "brokerapp";
private static final String CLIENT_SECRET = "secret";
@Test
public void testConsents() {
consumerRealmOAuth.openLoginForm();
LOGGER.debug("Clicking social " + IDP_OIDC_ALIAS);
loginPage.clickSocial(IDP_OIDC_ALIAS);
if (!driver.getCurrentUrl().contains("/realms/" + providerRealm.getName() + "/")) {
LOGGER.debug("Not on provider realm page, url: " + driver.getCurrentUrl());
}
Assertions.assertTrue(driver.getCurrentUrl().contains("/realms/" + providerRealm.getName() + "/"), "Driver should be on the provider realm page right now");
LOGGER.debug("Logging in");
loginPage.fillLogin(userFromProviderRealm.getUsername(), userFromProviderRealm.getPassword());
loginPage.submit();
consentPage.waitForPage();
consentPage.assertCurrent();
consentPage.confirm();
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
UsersResource consumerUsers = consumerRealm.admin().users();
Assertions.assertTrue(consumerUsers.count() > 0, "There must be at least one user");
List<UserRepresentation> users = consumerUsers.search("", 0, 5);
UserRepresentation foundUser = null;
for (UserRepresentation userRep : users) {
if (userRep.getUsername().equals(userFromProviderRealm.getUsername()) && userRep.getEmail().equals(userFromProviderRealm.admin().toRepresentation().getEmail())) {
foundUser = userRep;
break;
}
}
Assertions.assertNotNull(foundUser, "There must be user " + userFromProviderRealm.getUsername() + " in realm " + consumerRealm.getName());
// get user with the same username from provider realm
users = providerRealm.admin().users().search(null, foundUser.getFirstName(), foundUser.getLastName(), null, 0, 1);
Assertions.assertEquals(1, users.size(), "Same user should be in provider realm");
String userId = users.get(0).getId();
UserResource userResource = providerRealm.admin().users().get(userId);
// list consents
List<Map<String, Object>> consents = userResource.getConsents();
Assertions.assertEquals(1, consents.size(), "There should be one consent");
Map<String, Object> consent = consents.get(0);
Assertions.assertEquals(CLIENT_ID, consent.get("clientId"), "Consent should be given to " + CLIENT_ID);
// list sessions. Single client should be in user session
List<UserSessionRepresentation> sessions = userResource.getUserSessions();
Assertions.assertEquals(1, sessions.size(), "There should be one active session");
Assertions.assertEquals(1, sessions.get(0).getClients().size(), "There should be one client in user session");
// revoke consent
userResource.revokeConsent(CLIENT_ID);
// list consents
consents = userResource.getConsents();
Assertions.assertEquals(0, consents.size(), "There should be no consents");
// list sessions
sessions = userResource.getUserSessions();
Assertions.assertEquals(1, sessions.size(), "There should be one active session");
Assertions.assertEquals(0, sessions.get(0).getClients().size(), "There should be no client in user session");
AccountHelper.logout(providerRealm.admin(), userFromProviderRealm.getUsername());
}
/**
* KEYCLOAK-18954
*/
@Test
public void testRetrieveConsentsForUserWithClientsWithGrantedOfflineAccess() throws Exception {
RealmRepresentation providerRealmRep = providerRealm.admin().toRepresentation();
providerRealmRep.setAccountTheme("keycloak");
providerRealm.admin().update(providerRealmRep);
providerRealm.admin().clients().create(ClientConfigBuilder.create().clientId("test-app").redirectUris("*").publicClient(true).webOrigins("*").build());
ClientRepresentation providerAccountRep = providerRealm.admin().clients().findByClientId("test-app").get(0);
// add offline_scope to default account-console client scope
ClientScopeRepresentation offlineAccessScope = providerRealm.admin().getDefaultOptionalClientScopes().stream()
.filter(csr -> csr.getName().equals(OAuth2Constants.OFFLINE_ACCESS)).findFirst().get();
providerRealm.admin().clients().get(providerAccountRep.getId()).removeOptionalClientScope(offlineAccessScope.getId());
providerRealm.admin().clients().get(providerAccountRep.getId()).addDefaultClientScope(offlineAccessScope.getId());
// enable consent required to explicitly grant offline access
providerAccountRep.setConsentRequired(true);
providerAccountRep.setDirectAccessGrantsEnabled(true); // for offline token retrieval
providerRealm.admin().clients().get(providerAccountRep.getId()).update(providerAccountRep);
// navigate to account console and login
providerRealmOAuth.openLoginForm();
loginPage.waitForPage();
LOGGER.debug("Logging in");
loginPage.fillLogin(userFromProviderRealm.getUsername(), userFromProviderRealm.getPassword());
loginPage.submit();
consentPage.waitForPage();
LOGGER.debug("Grant consent for offline_access");
consentPage.assertCurrent();
consentPage.confirm();
// disable consent required again to enable direct grant token retrieval.
providerAccountRep.setConsentRequired(false);
providerRealm.admin().clients().get(providerAccountRep.getId()).update(providerAccountRep);
LOGGER.debug("Obtain offline_token");
AccessTokenResponse response = providerRealmOAuth
.scope(OAuth2Constants.SCOPE_OPENID +" " + OAuth2Constants.SCOPE_PROFILE + " " + OAuth2Constants.OFFLINE_ACCESS)
.doPasswordGrantRequest(userFromProviderRealm.getUsername(), userFromProviderRealm.getPassword());
assertNotNull(response.getRefreshToken());
LOGGER.debug("Check for Offline Token in consents");
List<Map<String, Object>> consents = providerRealm.admin().users().get(userFromProviderRealm.getId()).getConsents();
assertFalse(consents.isEmpty(), "Consents should not be empty");
assertTrue(consents.toString().contains("Offline Token"));
AccountHelper.logout(providerRealm.admin(), userFromProviderRealm.getUsername());
}
@Test
public void testConsentCancel() {
// setup account client to require consent
ClientResource accountClient = findClientByClientId(providerRealm.admin(), "test-app");
ClientRepresentation clientRepresentation = accountClient.toRepresentation();
clientRepresentation.setConsentRequired(true);
accountClient.update(clientRepresentation);
// navigate to account console and login
providerRealmOAuth.openLoginForm();
loginPage.fillLogin(userFromProviderRealm.getUsername(), userFromProviderRealm.getPassword());
loginPage.submit();
consentPage.assertCurrent();
consentPage.cancel();
// check an error page after cancelling the consent
assertTrue(driver.getPageSource().contains("Happy days"));
assertTrue(driver.getCurrentUrl().contains("error=access_denied"));
providerRealmOAuth.openLoginForm();
loginPage.fillLogin(userFromProviderRealm.getUsername(), userFromProviderRealm.getPassword());
loginPage.submit();
consentPage.confirm();
// successful login
assertFalse(driver.getCurrentUrl().contains("error"));
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
}
@Test
public void clientConsentRequiredAfterLogin() {
AuthorizationEndpointResponse response = userRealmOAuth.doLogin(userFromUserRealm.getUsername(), userFromUserRealm.getPassword());
AccessTokenResponse accessTokenResponse = userRealmOAuth.doAccessTokenRequest(response.getCode());
Assertions.assertNotNull(userRealmOAuth.parseLoginResponse().getCode());
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
EventRepresentation loginEvent = userRealmEvents.poll();
Assertions.assertNotNull(loginEvent);
Assertions.assertEquals(userFromUserRealm.getId(), loginEvent.getUserId());
Assertions.assertEquals(EventType.LOGIN.toString(), loginEvent.getType());
loginEvent.getDetails().forEach((key, value) -> {
switch (key) {
case Details.CODE_ID ->
Assertions.assertTrue(isUUID(value));
case Details.USERNAME -> Assertions.assertEquals(userFromUserRealm.getUsername(), value);
case Details.CONSENT -> Assertions.assertEquals(Details.CONSENT_VALUE_NO_CONSENT_REQUIRED, value);
case Details.REDIRECT_URI -> Assertions.assertEquals("http://127.0.0.1:8500/callback/oauth", value);
}
});
userRealm.updateWithCleanup(r -> r.enabledEventTypes("REFRESH_TOKEN_ERROR"));
String sessionId = loginEvent.getSessionId();
ClientRepresentation clientRepresentation = userRealm.admin().clients().findByClientId("test-app").get(0);
try {
clientRepresentation.setConsentRequired(true);
userRealm.admin().clients().get(clientRepresentation.getId()).update(clientRepresentation);
userRealmEvents.clear();
// try to refresh the token
// this fails as client no longer has requested consent from user
AccessTokenResponse refreshTokenResponse = userRealmOAuth.doRefreshTokenRequest(accessTokenResponse.getRefreshToken());
Assertions.assertEquals(OAuthErrorException.INVALID_SCOPE, refreshTokenResponse.getError());
Assertions.assertEquals("Client no longer has requested consent from user", refreshTokenResponse.getErrorDescription());
EventRepresentation refreshEvent = userRealmEvents.poll();
Assertions.assertNotNull(refreshEvent);
Assertions.assertNull(refreshEvent.getUserId());
Assertions.assertEquals(EventType.REFRESH_TOKEN_ERROR.toString(), refreshEvent.getType());
Assertions.assertNull(refreshTokenResponse.getRefreshToken());
Assertions.assertEquals(sessionId, refreshEvent.getSessionId());
Assertions.assertEquals(Errors.INVALID_TOKEN, refreshEvent.getError());
} finally {
clientRepresentation.setConsentRequired(false);
userRealm.admin().clients().get(clientRepresentation.getId()).update(clientRepresentation);
}
AccountHelper.logout(userRealm.admin(), userFromUserRealm.getUsername());
}
@Test
public void testConsentWithAdditionalClientAttributes() {
// setup account client to require consent
ClientResource accountClient = findClientByClientId(providerRealm.admin(), "test-app");
ClientRepresentation clientRepresentation = accountClient.toRepresentation();
clientRepresentation.setConsentRequired(true);
clientRepresentation.getAttributes().put(ClientModel.LOGO_URI,"https://www.keycloak.org/resources/images/keycloak_logo_480x108.png");
clientRepresentation.getAttributes().put(ClientModel.POLICY_URI,"https://www.keycloak.org/policy");
clientRepresentation.getAttributes().put(ClientModel.TOS_URI,"https://www.keycloak.org/tos");
accountClient.update(clientRepresentation);
// navigate to account console and login
providerRealmOAuth.openLoginForm();
loginPage.fillLogin(userFromProviderRealm.getUsername(), userFromProviderRealm.getPassword());
loginPage.submit();
consentPage.assertCurrent();
assertTrue(driver.findElement(By.xpath("//img[@src='https://www.keycloak.org/resources/images/keycloak_logo_480x108.png']")).isDisplayed(), "logoUri must be presented");
assertTrue(driver.findElement(By.xpath("//a[@href='https://www.keycloak.org/policy']")).isDisplayed(), "policyUri must be presented");
assertTrue(driver.findElement(By.xpath("//a[@href='https://www.keycloak.org/tos']")).isDisplayed(), "tosUri must be presented");
consentPage.confirm();
// successful login
assertTrue(driver.getPageSource().contains("Happy days"), "Test user should be successfully logged in.");
AccountHelper.logout(providerRealm.admin(), userFromProviderRealm.getUsername());
}
private static 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", "http://localhost:8080/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/auth");
config.put("tokenUrl", "http://localhost:8080/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/token");
config.put("logoutUrl", "http://localhost:8080/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/logout");
config.put("userInfoUrl", "http://localhost:8080/realms/" + REALM_PROV_NAME + "/protocol/openid-connect/userinfo");
config.put("defaultScope", "email profile");
config.put("backchannelSupported", "true");
return idp;
}
private 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;
}
private boolean isUUID(String uuid) {
return 36 == uuid.length()
&& uuid.charAt(8) == '-'
&& uuid.charAt(13) == '-'
&& uuid.charAt(18) == '-'
&& uuid.charAt(23) == '-';
}
private static class UserRealmUserConf implements UserConfig {
@Override
public UserConfigBuilder configure(UserConfigBuilder builder) {
builder.username("user");
builder.password("password");
builder.email("user@local");
builder.emailVerified();
builder.name("Local", "User");
return builder;
}
}
private static class ProviderRealmUserConf implements UserConfig {
@Override
public UserConfigBuilder configure(UserConfigBuilder builder) {
builder.username("provider");
builder.password("password");
builder.email("provider@local");
builder.emailVerified();
builder.name("Provider", "User");
return builder;
}
}
private static class ProviderRealmClientConf implements ClientConfig {
@Override
public ClientConfigBuilder configure(ClientConfigBuilder builder) {
builder.clientId(CLIENT_ID);
builder.name(CLIENT_ID);
builder.secret(CLIENT_SECRET);
builder.consentRequired(true);
builder.redirectUris( "http://localhost:8080/realms/" + REALM_CONS_NAME + "/broker/" + IDP_OIDC_ALIAS + "/endpoint/*");
builder.adminUrl("http://localhost:8080/realms/" + REALM_CONS_NAME + "/broker/" + IDP_OIDC_ALIAS + "/endpoint");
return builder;
}
}
private static class ConsumerRealmConf implements RealmConfig {
@Override
public RealmConfigBuilder configure(RealmConfigBuilder builder) {
builder.identityProvider(setUpIdentityProvider());
return builder;
}
}
}

View file

@ -9,7 +9,6 @@ import org.keycloak.events.admin.ResourceType;
import org.keycloak.models.Constants;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.MappingsRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.testframework.annotations.InjectRealm;
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
@ -21,7 +20,6 @@ import org.keycloak.testframework.realm.ManagedRealm;
import org.keycloak.testframework.realm.UserConfigBuilder;
import org.keycloak.tests.utils.admin.AdminEventPaths;
import org.keycloak.tests.utils.admin.ApiUtil;
import org.keycloak.testsuite.events.TestEventsListenerProviderFactory;
import org.keycloak.testsuite.util.RoleBuilder;
import java.util.Collections;
@ -42,10 +40,6 @@ public class UserRoleTest extends AbstractUserTest {
@Test
public void roleMappings() {
RealmResource realm = managedRealm.admin();
// Enable events
RealmRepresentation realmRep = addTestEventListener(managedRealm.admin().toRepresentation());
managedRealm.admin().update(realmRep);
RoleRepresentation realmCompositeRole = RoleBuilder.create().name("realm-composite").singleAttribute("attribute1", "value1").build();
realm.roles().create(RoleBuilder.create().name("realm-role").build());
@ -239,16 +233,4 @@ public class UserRoleTest extends AbstractUserTest {
return null;
}
private RealmRepresentation addTestEventListener(RealmRepresentation rep) {
if (rep.getEventsListeners() == null) {
rep.setEventsListeners(new LinkedList<String>());
}
if (!rep.getEventsListeners().contains(TestEventsListenerProviderFactory.PROVIDER_ID)) {
rep.getEventsListeners().add(TestEventsListenerProviderFactory.PROVIDER_ID);
}
return rep;
}
}

View file

@ -1,72 +0,0 @@
/*
* 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.events;
import org.keycloak.events.Event;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventListenerTransaction;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.models.KeycloakSession;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class TestEventsListenerProvider implements EventListenerProvider {
private static final BlockingQueue<Event> events = new LinkedBlockingQueue<Event>();
private static final BlockingQueue<AdminEvent> adminEvents = new LinkedBlockingQueue<>();
private final EventListenerTransaction tx = new EventListenerTransaction((event, includeRepre) -> adminEvents.add(event), events::add);
public TestEventsListenerProvider(KeycloakSession session) {
session.getTransactionManager().enlistAfterCompletion(tx);
}
@Override
public void onEvent(Event event) {
tx.addEvent(event);
}
@Override
public void onEvent(AdminEvent event, boolean includeRepresentation) {
tx.addAdminEvent(event, includeRepresentation);
}
@Override
public void close() {
}
public static Event poll() {
return events.poll();
}
public static AdminEvent pollAdminEvent() {
return adminEvents.poll();
}
public static void clear() {
events.clear();
}
public static void clearAdminEvents() {
adminEvents.clear();
}
}

View file

@ -1,54 +0,0 @@
/*
* 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.events;
import org.keycloak.Config;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventListenerProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class TestEventsListenerProviderFactory implements EventListenerProviderFactory {
public static final String PROVIDER_ID = "event-queue";
@Override
public EventListenerProvider create(KeycloakSession session) {
return new TestEventsListenerProvider(session);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void close() {
}
@Override
public String getId() {
return PROVIDER_ID;
}
}

View file

@ -1,35 +0,0 @@
#
# 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.
#
#
# 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.
#
org.keycloak.testsuite.events.TestEventsListenerProviderFactory

View file

@ -1,505 +0,0 @@
/*
* 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.admin;
import org.jboss.arquillian.graphene.page.Page;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.models.ClientModel;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.UserSessionRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.ConsentPage;
import org.keycloak.testsuite.pages.ErrorPage;
import org.keycloak.testsuite.pages.LoginPage;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.AbstractTestRealmKeycloakTest.TEST_REALM_NAME;
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient;
import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
import static org.keycloak.testsuite.admin.ApiUtil.resetUserPassword;
import org.keycloak.testsuite.util.ClientBuilder;
import org.keycloak.testsuite.util.oauth.AccessTokenResponse;
import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse;
import org.openqa.selenium.By;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public class ConsentsTest extends AbstractKeycloakTest {
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 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 USER_FIRSTNAME = "User";
final static String USER_LASTNAME = "Tester";
protected RealmRepresentation createProviderRealm() {
RealmRepresentation realm = new RealmRepresentation();
realm.setRealm(REALM_PROV_NAME);
realm.setEnabled(true);
return realm;
}
protected RealmRepresentation createConsumerRealm() {
RealmRepresentation realm = new RealmRepresentation();
realm.setRealm(REALM_CONS_NAME);
realm.setEnabled(true);
return realm;
}
protected List<ClientRepresentation> createProviderClients() {
ClientRepresentation client = new ClientRepresentation();
client.setClientId(CLIENT_ID);
client.setName(CLIENT_ID);
client.setSecret(CLIENT_SECRET);
client.setEnabled(true);
client.setConsentRequired(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);
}
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;
}
protected String getUserLogin() {
return USER_LOGIN;
}
protected String getUserPassword() {
return USER_PASSWORD;
}
protected String getUserEmail() {
return USER_EMAIL;
}
protected String getUserFirstName() {
return USER_FIRSTNAME;
}
protected String getUserLastName() {
return USER_LASTNAME;
}
protected String providerRealmName() {
return REALM_PROV_NAME;
}
protected String consumerRealmName() {
return REALM_CONS_NAME;
}
protected String getIDPAlias() {
return IDP_OIDC_ALIAS;
}
@Rule
public AssertEvents events = new AssertEvents(this);
@Page
protected LoginPage accountLoginPage;
@Page
protected ConsentPage consentPage;
@Page
protected AppPage appPage;
@Page
protected ErrorPage errorPage;
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation providerRealm = createProviderRealm();
RealmRepresentation consumerRealm = createConsumerRealm();
RealmRepresentation realmRepresentation = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
testRealms.add(providerRealm);
testRealms.add(consumerRealm);
testRealms.add(realmRepresentation);
}
@Before
public void createUser() {
log.debug("creating user for realm " + providerRealmName());
UserRepresentation user = new UserRepresentation();
user.setUsername(getUserLogin());
user.setEmail(getUserEmail());
user.setFirstName(getUserFirstName());
user.setLastName(getUserLastName());
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<ClientRepresentation> 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);
}
}
createAppClientInRealm(consumerRealmName());
}
protected String getAuthRoot() {
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;
}
private void waitForPage(String title) {
long startAt = System.currentTimeMillis();
while (!driver.getTitle().toLowerCase().contains(title)
&& System.currentTimeMillis() - startAt < 200) {
try {
Thread.sleep(5);
} catch (InterruptedException ignore) {}
}
}
@After
public void cleanUser() {
String userId = adminClient.realm(providerRealmName()).users().search(getUserLogin()).get(0).getId();
adminClient.realm(providerRealmName()).users().delete(userId);
}
@Test
public void testConsents() {
oauth.realm(consumerRealmName());
oauth.redirectUri(oauth.SERVER_ROOT + "/auth/realms/" + consumerRealmName() + "/app/auth");
oauth.openLoginForm();
log.debug("Clicking social " + getIDPAlias());
accountLoginPage.clickSocial(getIDPAlias());
if (!driver.getCurrentUrl().contains("/auth/realms/" + providerRealmName() + "/")) {
log.debug("Not on provider realm page, url: " + driver.getCurrentUrl());
}
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());
waitForPage("grant access");
Assert.assertTrue(consentPage.isCurrent());
consentPage.confirm();
Assert.assertTrue("We must be on correct realm right now",
driver.getCurrentUrl().contains("/auth/realms/" + consumerRealmName() + "/"));
UsersResource consumerUsers = adminClient.realm(consumerRealmName()).users();
Assert.assertTrue("There must be at least one user", consumerUsers.count() > 0);
List<UserRepresentation> users = consumerUsers.search("", 0, 5);
UserRepresentation foundUser = null;
for (UserRepresentation user : users) {
if (user.getUsername().equals(getUserLogin()) && user.getEmail().equals(getUserEmail())) {
foundUser = user;
break;
}
}
Assert.assertNotNull("There must be user " + getUserLogin() + " in realm " + consumerRealmName(),
foundUser);
// get user with the same username from provider realm
RealmResource providerRealm = adminClient.realm(providerRealmName());
users = providerRealm.users().search(null, foundUser.getFirstName(), foundUser.getLastName(), null, 0, 1);
Assert.assertEquals("Same user should be in provider realm", 1, users.size());
String userId = users.get(0).getId();
UserResource userResource = providerRealm.users().get(userId);
// list consents
List<Map<String, Object>> consents = userResource.getConsents();
Assert.assertEquals("There should be one consent", 1, consents.size());
Map<String, Object> consent = consents.get(0);
Assert.assertEquals("Consent should be given to " + CLIENT_ID, CLIENT_ID, consent.get("clientId"));
// list sessions. Single client should be in user session
List<UserSessionRepresentation> sessions = userResource.getUserSessions();
Assert.assertEquals("There should be one active session", 1, sessions.size());
Assert.assertEquals("There should be one client in user session", 1, sessions.get(0).getClients().size());
// revoke consent
userResource.revokeConsent(CLIENT_ID);
// list consents
consents = userResource.getConsents();
Assert.assertEquals("There should be no consents", 0, consents.size());
// list sessions
sessions = userResource.getUserSessions();
Assert.assertEquals("There should be one active session", 1, sessions.size());
Assert.assertEquals("There should be no client in user session", 0, sessions.get(0).getClients().size());
// oauth clean up
oauth.realm("test");
oauth.redirectUri(oauth.SERVER_ROOT + "/auth/realms/master/app/auth");
}
/**
* KEYCLOAK-18954
*/
@Test
public void testRetrieveConsentsForUserWithClientsWithGrantedOfflineAccess() throws Exception {
RealmResource providerRealm = adminClient.realm(providerRealmName());
RealmRepresentation providerRealmRep = providerRealm.toRepresentation();
providerRealmRep.setAccountTheme("keycloak");
providerRealm.update(providerRealmRep);
providerRealm.clients().create(ClientBuilder.create().clientId("test-app").redirectUris("*").addWebOrigin("*").publicClient().build());
ClientRepresentation providerAccountRep = providerRealm.clients().findByClientId("test-app").get(0);
// add offline_scope to default account-console client scope
ClientScopeRepresentation offlineAccessScope = providerRealm.getDefaultOptionalClientScopes().stream()
.filter(csr -> csr.getName().equals(OAuth2Constants.OFFLINE_ACCESS)).findFirst().get();
providerRealm.clients().get(providerAccountRep.getId()).removeOptionalClientScope(offlineAccessScope.getId());
providerRealm.clients().get(providerAccountRep.getId()).addDefaultClientScope(offlineAccessScope.getId());
// enable consent required to explicitly grant offline access
providerAccountRep.setConsentRequired(true);
providerAccountRep.setDirectAccessGrantsEnabled(true); // for offline token retrieval
providerRealm.clients().get(providerAccountRep.getId()).update(providerAccountRep);
List<UserRepresentation> searchResult = providerRealm.users().search(getUserLogin());
UserRepresentation user = searchResult.get(0);
accountLoginPage.open(providerRealmName());
waitForPage("Sign in to provider");
log.debug("Logging in");
accountLoginPage.login(getUserLogin(), getUserPassword());
waitForPage("grant access");
log.debug("Grant consent for offline_access");
Assert.assertTrue(consentPage.isCurrent());
consentPage.confirm();
// disable consent required again to enable direct grant token retrieval.
providerAccountRep.setConsentRequired(false);
providerRealm.clients().get(providerAccountRep.getId()).update(providerAccountRep);
log.debug("Obtain offline_token");
AccessTokenResponse response = oauth.realm(providerRealmRep.getRealm())
.client(providerAccountRep.getClientId())
.scope(OAuth2Constants.SCOPE_OPENID +" " + OAuth2Constants.SCOPE_PROFILE + " " + OAuth2Constants.OFFLINE_ACCESS)
.doPasswordGrantRequest(getUserLogin(), getUserPassword());
assertNotNull(response.getRefreshToken());
log.debug("Check for Offline Token in consents");
List<Map<String, Object>> consents = providerRealm.users().get(user.getId()).getConsents();
assertFalse("Consents should not be empty", consents.isEmpty());
assertTrue(consents.toString().contains("Offline Token"));
}
@Test
public void testConsentCancel() {
// setup account client to require consent
createAppClientInRealm(providerRealmName());
RealmResource providerRealm = adminClient.realm(providerRealmName());
ClientResource accountClient = findClientByClientId(providerRealm, "test-app");
ClientRepresentation clientRepresentation = accountClient.toRepresentation();
clientRepresentation.setConsentRequired(true);
accountClient.update(clientRepresentation);
// setup correct realm
oauth.realm(providerRealmName());
// navigate to account console and login
oauth.openLoginForm();
loginPage.form().login(getUserLogin(), getUserPassword());
consentPage.assertCurrent();
consentPage.cancel();
// check an error page after cancelling the consent
assertTrue(driver.getTitle().contains("AUTH_RESPONSE"));
assertTrue(driver.getCurrentUrl().contains("error=access_denied"));
oauth.openLoginForm();
loginPage.form().login(getUserLogin(), getUserPassword());
consentPage.confirm();
// successful login
assertFalse(driver.getCurrentUrl().contains("error"));
assertTrue("Test user should be successfully logged in.", driver.getTitle().contains("AUTH_RESPONSE"));
}
@Test
public void clientConsentRequiredAfterLogin() {
oauth.realm(TEST_REALM_NAME).client("test-app", "password");
AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
AccessTokenResponse accessTokenResponse = oauth.doAccessTokenRequest(response.getCode());
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
Assert.assertNotNull(oauth.parseLoginResponse().getCode());
EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
String sessionId = loginEvent.getSessionId();
ClientRepresentation clientRepresentation = adminClient.realm(TEST_REALM_NAME).clients().findByClientId("test-app").get(0);
try {
clientRepresentation.setConsentRequired(true);
adminClient.realm(TEST_REALM_NAME).clients().get(clientRepresentation.getId()).update(clientRepresentation);
events.clear();
// try to refresh the token
// this fails as client no longer has requested consent from user
AccessTokenResponse refreshTokenResponse = oauth.doRefreshTokenRequest(accessTokenResponse.getRefreshToken());
Assert.assertEquals(OAuthErrorException.INVALID_SCOPE, refreshTokenResponse.getError());
Assert.assertEquals("Client no longer has requested consent from user", refreshTokenResponse.getErrorDescription());
events.expectRefresh(accessTokenResponse.getRefreshToken(), sessionId).user((String) null).clearDetails().error(Errors.INVALID_TOKEN).assertEvent();
} finally {
clientRepresentation.setConsentRequired(false);
adminClient.realm(TEST_REALM_NAME).clients().get(clientRepresentation.getId()).update(clientRepresentation);
}
}
@Test
public void testConsentWithAdditionalClientAttributes() {
// setup account client to require consent
RealmResource providerRealm = adminClient.realm(providerRealmName());
ClientResource accountClient = findClientByClientId(providerRealm, "test-app");
ClientRepresentation clientRepresentation = accountClient.toRepresentation();
clientRepresentation.setConsentRequired(true);
clientRepresentation.getAttributes().put(ClientModel.LOGO_URI,"https://www.keycloak.org/resources/images/keycloak_logo_480x108.png");
clientRepresentation.getAttributes().put(ClientModel.POLICY_URI,"https://www.keycloak.org/policy");
clientRepresentation.getAttributes().put(ClientModel.TOS_URI,"https://www.keycloak.org/tos");
accountClient.update(clientRepresentation);
// setup correct realm
oauth.realm(providerRealmName());
// navigate to account console and login
oauth.openLoginForm();
loginPage.form().login(getUserLogin(), getUserPassword());
consentPage.assertCurrent();
assertTrue("logoUri must be presented", driver.findElement(By.xpath("//img[@src='https://www.keycloak.org/resources/images/keycloak_logo_480x108.png']")).isDisplayed());
assertTrue("policyUri must be presented", driver.findElement(By.xpath("//a[@href='https://www.keycloak.org/policy']")).isDisplayed());
assertTrue("tosUri must be presented", driver.findElement(By.xpath("//a[@href='https://www.keycloak.org/tos']")).isDisplayed());
consentPage.confirm();
// successful login
assertTrue("Test user should be successfully logged in.", driver.getTitle().contains("AUTH_RESPONSE"));
}
private String getAccountUrl(String realmName) {
return getAuthRoot() + "/auth/realms/" + realmName + "/account";
}
}