diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountApplicationsPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountApplicationsPage.java deleted file mode 100644 index d3243a1d64..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/AccountApplicationsPage.java +++ /dev/null @@ -1,150 +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.pages; - -import org.keycloak.services.Urls; -import org.openqa.selenium.By; -import org.openqa.selenium.WebElement; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.keycloak.testsuite.util.UIUtils.clickLink; -import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; - -/** - * @author Marek Posolda - */ -public class AccountApplicationsPage extends AbstractAccountPage { - - @Override - public boolean isCurrent() { - return driver.getTitle().contains("Account Management") && driver.getCurrentUrl().endsWith("/account/applications"); - } - - @Override - public void open() { - driver.navigate().to(getPath()); - waitForPageToLoad(); - } - - private String getPath() { - return Urls.accountApplicationsPage(getAuthServerRoot(), "test").toString(); - } - - public void revokeGrant(String clientId) { - clickLink(driver.findElement(By.id("revoke-" + clientId))); - } - - public Map getApplications() { - Map table = new HashMap(); - for (WebElement r : driver.findElements(By.tagName("tr"))) { - int count = 0; - AppEntry currentEntry = null; - - for (WebElement col : r.findElements(By.tagName("td"))) { - count++; - switch (count) { - case 1: - currentEntry = new AppEntry(); - String client = col.getText(); - WebElement link = null; - try { - link = col.findElement(By.tagName("a")); - String href = link.getAttribute("href"); - currentEntry.setHref(href); - } catch (Exception e) { - //ignore - } - table.put(client, currentEntry); - break; - case 2: - String rolesStr = col.getText(); - String[] roles = rolesStr.split(","); - for (String role : roles) { - role = role.trim(); - currentEntry.addAvailableRole(role); - } - break; - case 3: - String clientScopesStr = col.getText(); - if (clientScopesStr.isEmpty()) break; - String[] clientScopes = clientScopesStr.split(","); - for (String clientScope : clientScopes) { - clientScope = clientScope.trim(); - currentEntry.addGrantedClientScope(clientScope); - } - break; - case 4: - String additionalGrant = col.getText(); - if (additionalGrant.isEmpty()) break; - String[] grants = additionalGrant.split(","); - for (String grant : grants) { - grant = grant.trim(); - currentEntry.addAdditionalGrant(grant); - } - break; - } - } - } - table.remove("Application"); - return table; - } - - public static class AppEntry { - - private final List rolesAvailable = new ArrayList(); - private final List clientScopesGranted = new ArrayList(); - private final List additionalGrants = new ArrayList<>(); - private String href = null; - - private void addAvailableRole(String role) { - rolesAvailable.add(role); - } - - private void addGrantedClientScope(String clientScope) { - clientScopesGranted.add(clientScope); - } - - private void addAdditionalGrant(String grant) { - additionalGrants.add(grant); - } - - public void setHref(String href) { - this.href = href; - } - - public String getHref() { - return this.href; - } - - public List getRolesAvailable() { - return rolesAvailable; - } - - public List getClientScopesGranted() { - return clientScopesGranted; - } - - public List getAdditionalGrants() { - return additionalGrants; - } - } -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/OfflineServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/OfflineServletsAdapterTest.java index db4b270774..338f717cdc 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/OfflineServletsAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/OfflineServletsAdapterTest.java @@ -2,33 +2,32 @@ package org.keycloak.testsuite.adapter.servlet; import javax.ws.rs.core.UriBuilder; import java.util.List; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.ArrayList; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.graphene.page.Page; import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; -import org.keycloak.common.Profile; -import org.keycloak.events.Details; -import org.keycloak.events.EventType; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest; import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter; import org.keycloak.testsuite.adapter.page.OfflineToken; import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; -import org.keycloak.testsuite.arquillian.annotation.DisableFeature; import org.keycloak.testsuite.updaters.ClientAttributeUpdater; +import org.keycloak.testsuite.util.AccountHelper; import org.keycloak.testsuite.util.InfinispanTestTimeServiceRule; import org.keycloak.testsuite.util.WaitUtils; import org.keycloak.testsuite.utils.arquillian.ContainerConstants; -import org.keycloak.testsuite.pages.AccountApplicationsPage; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.pages.OAuthGrantPage; import org.keycloak.testsuite.utils.io.IOUtil; import org.keycloak.util.TokenUtil; -import org.hamcrest.Matchers; import org.openqa.selenium.By; import java.io.Closeable; @@ -54,7 +53,6 @@ import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; @AppServerContainer(ContainerConstants.APP_SERVER_EAP) @AppServerContainer(ContainerConstants.APP_SERVER_EAP6) @AppServerContainer(ContainerConstants.APP_SERVER_EAP71) -@DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest { @Rule @@ -64,8 +62,6 @@ public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest { @Page protected LoginPage loginPage; @Page - protected AccountApplicationsPage accountAppPage; - @Page protected OAuthGrantPage oauthGrantPage; @Rule @@ -181,19 +177,17 @@ public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest { events.clear(); - // Go to account service and revoke grant - accountAppPage.open(); + // Check that Offline Token is granted + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + String actualValue = String.valueOf(((LinkedHashMap) ((ArrayList) userConsents.get(0).get("additionalGrants")).get(0)).get("key")); + Assert.assertEquals("Offline Token", actualValue); - List additionalGrants = accountAppPage.getApplications().get(OFFLINE_CLIENT_ID).getAdditionalGrants(); - assertThat(additionalGrants.size(), is(1)); - assertThat(additionalGrants.get(0), is("Offline Token")); - - accountAppPage.revokeGrant(OFFLINE_CLIENT_ID); + // Revoke consents + AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, OFFLINE_CLIENT_ID); pause(500); - assertThat(accountAppPage.getApplications().get(OFFLINE_CLIENT_ID).getAdditionalGrants().size(), is(0)); - events.expect(EventType.REVOKE_GRANT) - .client("account").detail(Details.REVOKED_CLIENT, OFFLINE_CLIENT_ID).assertEvent(); + userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + assertThat(userConsents.size(), is(0)); // Assert refresh doesn't work now (increase time one more time) setAdapterAndServerTimeOffset(19999); @@ -238,15 +232,13 @@ public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest { assertThat(offlineTokenPage.getRefreshToken(), notNullValue()); assertThat(offlineTokenPage.getRefreshToken().getType(), is(TokenUtil.TOKEN_TYPE_OFFLINE)); - accountAppPage.open(); - AccountApplicationsPage.AppEntry offlineClient = accountAppPage.getApplications().get(OFFLINE_CLIENT_ID); - assertThat(offlineClient.getClientScopesGranted(), Matchers.hasItem(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT)); - assertThat(offlineClient.getAdditionalGrants(), Matchers.hasItem("Offline Token")); + // Check that the client scopes have been granted by the user + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertTrue(((List) userConsents.get(0).get("grantedClientScopes")).stream().anyMatch(p -> p.equals("offline_access"))); + String actualValue = String.valueOf(((LinkedHashMap) ((ArrayList) userConsents.get(0).get("additionalGrants")).get(0)).get("key")); + Assert.assertEquals("Offline Token", actualValue); - //This was necessary to be introduced, otherwise other testcases will fail - accountAppPage.logout(); - assertCurrentUrlDoesntStartWith(offlineTokenPage); - loginPage.assertCurrent(); + AccountHelper.logout(adminClient.realm(TEST), DEFAULT_USERNAME); } finally { events.clear(); resetTimeOffsetAuthenticated(); @@ -260,7 +252,6 @@ public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest { private void resetTimeOffsetAuthenticated() { resetTimeOffsetAuthenticated(DEFAULT_USERNAME, DEFAULT_PASSWORD); } - /** * Reset time offset for remote environment. * After the token expiration, process of re-authentication is necessary. @@ -278,9 +269,9 @@ public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest { if (loginPage.isCurrent()) { loginPage.login(username, password); waitForPageToLoad(); - accountAppPage.open(); - accountAppPage.logout(); + AccountHelper.logout(adminClient.realm(TEST), DEFAULT_USERNAME); } setTimeOffset(0); } + } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBaseBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBaseBrokerTest.java index 8100c1fc9b..a6d12307ea 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBaseBrokerTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractBaseBrokerTest.java @@ -33,7 +33,6 @@ import org.keycloak.services.resources.RealmsResource; import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.arquillian.annotation.DisableFeature; -import org.keycloak.testsuite.pages.AccountApplicationsPage; import org.keycloak.testsuite.pages.AccountFederatedIdentityPage; import org.keycloak.testsuite.pages.AccountUpdateProfilePage; import org.keycloak.testsuite.pages.ErrorPage; @@ -129,9 +128,6 @@ public abstract class AbstractBaseBrokerTest extends AbstractKeycloakTest { @Page protected AccountFederatedIdentityPage accountFederatedIdentityPage; - @Page - protected AccountApplicationsPage accountApplicationsPage; - @Page protected OAuthGrantPage grantPage; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java index 2e13634c47..a939891ef6 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java @@ -28,7 +28,6 @@ import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.common.Profile; import org.keycloak.events.Details; -import org.keycloak.events.EventType; import org.keycloak.models.ClientScopeModel; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.representations.AccessToken; @@ -37,21 +36,20 @@ import org.keycloak.representations.idm.ClientScopeRepresentation; import org.keycloak.representations.idm.EventRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.admin.ApiUtil; -import org.keycloak.testsuite.arquillian.annotation.DisableFeature; import org.keycloak.testsuite.arquillian.annotation.EnableFeature; -import org.keycloak.testsuite.pages.AccountApplicationsPage; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.ErrorPage; import org.keycloak.testsuite.pages.LogoutConfirmPage; import org.keycloak.testsuite.pages.OAuthGrantPage; import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.ProtocolMapperUtil; +import org.keycloak.testsuite.util.AccountHelper; import org.openqa.selenium.By; +import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -61,22 +59,22 @@ import javax.ws.rs.core.Response; import static org.junit.Assert.assertEquals; import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId; +import static org.keycloak.testsuite.auth.page.AuthRealm.TEST; /** * @author Viliam Rockai */ -@DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) public class OAuthGrantTest extends AbstractKeycloakTest { public static final String THIRD_PARTY_APP = "third-party"; public static final String REALM_NAME = "test"; + private final String DEFAULT_USERNAME = "test-user@localhost"; + private final String DEFAULT_PASSWORD = "password"; @Rule public AssertEvents events = new AssertEvents(this); @Page protected OAuthGrantPage grantPage; - @Page - protected AccountApplicationsPage accountAppsPage; @Page protected LogoutConfirmPage logoutConfirmPage; @@ -100,7 +98,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { @Test public void oauthGrantAcceptTest() { oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); grantPage.assertGrants(OAuthGrantPage.PROFILE_CONSENT_TEXT, OAuthGrantPage.EMAIL_CONSENT_TEXT, OAuthGrantPage.ROLES_CONSENT_TEXT); @@ -134,14 +132,10 @@ public class OAuthGrantTest extends AbstractKeycloakTest { events.expectCodeToToken(codeId, loginEvent.getSessionId()).client(THIRD_PARTY_APP).assertEvent(); - accountAppsPage.open(); + AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, THIRD_PARTY_APP); - assertEquals(1, driver.findElements(By.id("revoke-third-party")).size()); - - accountAppsPage.revokeGrant(THIRD_PARTY_APP); - - events.expect(EventType.REVOKE_GRANT) - .client("account").detail(Details.REVOKED_CLIENT, THIRD_PARTY_APP).assertEvent(); + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertEquals(userConsents.size(), 0); assertEquals(0, driver.findElements(By.id("revoke-third-party")).size()); } @@ -149,7 +143,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { @Test public void oauthGrantCancelTest() { oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); grantPage.assertGrants(OAuthGrantPage.PROFILE_CONSENT_TEXT, OAuthGrantPage.EMAIL_CONSENT_TEXT, OAuthGrantPage.ROLES_CONSENT_TEXT); @@ -168,10 +162,10 @@ public class OAuthGrantTest extends AbstractKeycloakTest { } @Test - public void oauthGrantNotShownWhenAlreadyGranted() { + public void oauthGrantNotShownWhenAlreadyGranted() throws IOException { // Grant permissions on grant screen oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); grantPage.accept(); @@ -181,11 +175,11 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED) .assertEvent(); - // Assert permissions granted on Account mgmt. applications page - accountAppsPage.open(); - AccountApplicationsPage.AppEntry thirdPartyEntry = accountAppsPage.getApplications().get(THIRD_PARTY_APP); - thirdPartyEntry.getClientScopesGranted().contains(OAuthGrantPage.PROFILE_CONSENT_TEXT); - thirdPartyEntry.getClientScopesGranted().contains(OAuthGrantPage.EMAIL_CONSENT_TEXT); + // Assert permissions granted on Account mgmt. + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + + Assert.assertTrue(((List) userConsents.get(0).get("grantedClientScopes")).stream().anyMatch(p -> p.equals("profile"))); + Assert.assertTrue(((List) userConsents.get(0).get("grantedClientScopes")).stream().anyMatch(p -> p.equals("email"))); // Open login form and assert grantPage not shown oauth.openLoginForm(); @@ -197,11 +191,10 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .client(THIRD_PARTY_APP).assertEvent(); // Revoke grant in account mgmt. - accountAppsPage.open(); - accountAppsPage.revokeGrant(THIRD_PARTY_APP); + AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, THIRD_PARTY_APP); - events.expect(EventType.REVOKE_GRANT) - .client("account").detail(Details.REVOKED_CLIENT, THIRD_PARTY_APP).assertEvent(); + userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertEquals(userConsents.size(), 0); // Open login form again and assert grant Page is shown oauth.openLoginForm(); @@ -210,10 +203,10 @@ public class OAuthGrantTest extends AbstractKeycloakTest { } @Test - public void oauthGrantAddAnotherScope() { + public void oauthGrantAddAnotherScope() throws IOException { // Grant permissions on grant screen oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); // Create new clientScope and add to client RealmResource appRealm = adminClient.realm(REALM_NAME); @@ -238,9 +231,8 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .assertEvent(); // Assert new clientScope not yet in account mgmt - accountAppsPage.open(); - AccountApplicationsPage.AppEntry appEntry = accountAppsPage.getApplications().get(THIRD_PARTY_APP); - Assert.assertFalse(appEntry.getClientScopesGranted().contains("foo-scope")); + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertFalse(((List) userConsents.get(0).get("grantedClientScopes")).stream().anyMatch(p -> p.equals("foo-scope"))); // Show grant page another time. Just new clientScope is on the page oauth.openLoginForm(); @@ -254,14 +246,14 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .assertEvent(); // Go to account mgmt. Everything is granted now - accountAppsPage.open(); - appEntry = accountAppsPage.getApplications().get(THIRD_PARTY_APP); - Assert.assertTrue(appEntry.getClientScopesGranted().contains("foo-scope")); + userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertTrue(((List) userConsents.get(0).get("grantedClientScopes")).stream().anyMatch(p -> p.equals("foo-scope"))); // Revoke - accountAppsPage.revokeGrant(THIRD_PARTY_APP); - events.expect(EventType.REVOKE_GRANT) - .client("account").detail(Details.REVOKED_CLIENT, THIRD_PARTY_APP).assertEvent(); + AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, THIRD_PARTY_APP); + + userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertEquals(userConsents.size(), 0); // Cleanup thirdParty.removeDefaultClientScope(fooScopeId); @@ -286,7 +278,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { // Assert clientScope not on grant screen when not requested oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); List grants = grantPage.getDisplayedGrants(); Assert.assertFalse(grants.contains("foo-scope")); @@ -300,7 +292,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .assertEvent(); oauth.scope("foo-scope"); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); grants = grantPage.getDisplayedGrants(); Assert.assertTrue(grants.contains("foo-scope")); @@ -312,10 +304,10 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .assertEvent(); // Revoke - accountAppsPage.open(); - accountAppsPage.revokeGrant(THIRD_PARTY_APP); - events.expect(EventType.REVOKE_GRANT) - .client("account").detail(Details.REVOKED_CLIENT, THIRD_PARTY_APP).assertEvent(); + AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, THIRD_PARTY_APP); + + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertEquals(userConsents.size(), 0); // cleanup oauth.scope(null); @@ -324,7 +316,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { @Test @EnableFeature(value = Profile.Feature.DYNAMIC_SCOPES, skipRestart = true) - public void oauthGrantDynamicScopeParamRequired() { + public void oauthGrantDynamicScopeParamRequired() throws IOException { RealmResource appRealm = adminClient.realm(REALM_NAME); ClientResource thirdParty = findClientByClientId(appRealm, THIRD_PARTY_APP); @@ -347,7 +339,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { // Assert clientScope not on grant screen when not requested oauth.clientId(THIRD_PARTY_APP); oauth.scope("foo-dynamic-scope:withparam"); - oauth.doLogin("test-user@localhost", "password"); + oauth.doLogin(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); List grants = grantPage.getDisplayedGrants(); Assert.assertTrue(grants.contains("foo-dynamic-scope: withparam")); @@ -372,7 +364,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { // login again to check whether the Dynamic scope and only the dynamic scope is requested again oauth.scope("foo-dynamic-scope:withparam"); - oauth.doLogin("test-user@localhost", "password"); + oauth.doLogin(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); grants = grantPage.getDisplayedGrants(); Assert.assertEquals(1, grants.size()); @@ -385,10 +377,10 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .assertEvent(); // Revoke - accountAppsPage.open(); - accountAppsPage.revokeGrant(THIRD_PARTY_APP); - events.expect(EventType.REVOKE_GRANT) - .client("account").detail(Details.REVOKED_CLIENT, THIRD_PARTY_APP).assertEvent(); + AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, THIRD_PARTY_APP); + + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertEquals(userConsents.size(), 0); // cleanup oauth.scope(null); @@ -420,7 +412,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { // Login oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); grantPage.assertGrants(OAuthGrantPage.EMAIL_CONSENT_TEXT, OAuthGrantPage.PROFILE_CONSENT_TEXT, OAuthGrantPage.ROLES_CONSENT_TEXT, "foo-addr"); grantPage.accept(); @@ -431,11 +423,10 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .assertEvent(); // Go to user's application screen - accountAppsPage.open(); - Assert.assertTrue(accountAppsPage.isCurrent()); - Map apps = accountAppsPage.getApplications(); - Assert.assertTrue(apps.containsKey("third-party")); - Assert.assertTrue(apps.get("third-party").getClientScopesGranted().contains("foo-addr")); + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + + Assert.assertEquals("third-party", userConsents.get(0).get("clientId")); + Assert.assertTrue(((List) userConsents.get(0).get("grantedClientScopes")).stream().anyMatch(p -> p.equals("foo-addr"))); // Login as admin and see the consent screen of particular user UserResource user = ApiUtil.findUserByUsernameId(appRealm, "test-user@localhost"); @@ -452,10 +443,10 @@ public class OAuthGrantTest extends AbstractKeycloakTest { .client(THIRD_PARTY_APP).assertEvent(); // Revoke - accountAppsPage.open(); - accountAppsPage.revokeGrant(THIRD_PARTY_APP); - events.expect(EventType.REVOKE_GRANT) - .client("account").detail(Details.REVOKED_CLIENT, THIRD_PARTY_APP).assertEvent(); + AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, THIRD_PARTY_APP); + + userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME); + Assert.assertEquals(userConsents.size(), 0); // Cleanup thirdParty.removeDefaultClientScope(fooScopeId); @@ -464,7 +455,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { @Test public void oauthGrantExpiredAuthSession() throws Exception { oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); @@ -480,7 +471,6 @@ public class OAuthGrantTest extends AbstractKeycloakTest { Assert.assertEquals(backToAppLink, thirdParty.getBaseUrl()); } - // KEYCLOAK-7470 @Test public void oauthGrantOrderedClientScopes() throws Exception { @@ -491,15 +481,17 @@ public class OAuthGrantTest extends AbstractKeycloakTest { ClientScopeRepresentation emailRep = emailScope.toRepresentation(); emailRep.getAttributes().put(ClientScopeModel.GUI_ORDER, "1"); emailScope.update(emailRep); + Assert.assertEquals("1", emailRep.getAttributes().get(ClientScopeModel.GUI_ORDER)); ClientScopeResource profileScope = ApiUtil.findClientScopeByName(appRealm, "profile"); ClientScopeRepresentation profileRep = profileScope.toRepresentation(); profileRep.getAttributes().put(ClientScopeModel.GUI_ORDER, "2"); profileScope.update(profileRep); + Assert.assertEquals("2", profileRep.getAttributes().get(ClientScopeModel.GUI_ORDER)); // Display consent screen --- assert email, then profile oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); grantPage.assertCurrent(); List displayedScopes = grantPage.getDisplayedGrants(); @@ -507,27 +499,15 @@ public class OAuthGrantTest extends AbstractKeycloakTest { Assert.assertEquals("User profile", displayedScopes.get(1)); grantPage.accept(); - // Display account mgmt --- assert email, then profile - accountAppsPage.open(); - displayedScopes = accountAppsPage.getApplications().get(THIRD_PARTY_APP).getClientScopesGranted(); - Assert.assertEquals("Email address", displayedScopes.get(0)); - Assert.assertEquals("User profile", displayedScopes.get(1)); - - // Update GUI Order --- email=3 emailRep = emailScope.toRepresentation(); emailRep.getAttributes().put(ClientScopeModel.GUI_ORDER, "3"); emailScope.update(emailRep); - - - // Display account mgmt --- assert profile, then email - accountAppsPage.open(); - displayedScopes = accountAppsPage.getApplications().get(THIRD_PARTY_APP).getClientScopesGranted(); - Assert.assertEquals("User profile", displayedScopes.get(0)); - Assert.assertEquals("Email address", displayedScopes.get(1)); + Assert.assertEquals("3", emailRep.getAttributes().get(ClientScopeModel.GUI_ORDER)); // Revoke grant and display consent screen --- assert profile, then email - accountAppsPage.revokeGrant(THIRD_PARTY_APP); + AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, THIRD_PARTY_APP); + oauth.openLoginForm(); grantPage.assertCurrent(); displayedScopes = grantPage.getDisplayedGrants(); @@ -541,7 +521,7 @@ public class OAuthGrantTest extends AbstractKeycloakTest { public void oauthGrantUserNotLoggedOutAfterConsentRevoke() throws Exception { // Login oauth.clientId(THIRD_PARTY_APP); - oauth.doLoginGrant("test-user@localhost", "password"); + oauth.doLoginGrant(DEFAULT_USERNAME, DEFAULT_PASSWORD); // Confirm consent screen grantPage.assertCurrent(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java index 6f27b5b753..73c403df52 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java @@ -29,7 +29,6 @@ import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.RoleResource; import org.keycloak.admin.client.resource.UserResource; -import org.keycloak.common.Profile; import org.keycloak.common.constants.ServiceAccountConstants; import org.keycloak.crypto.Algorithm; import org.keycloak.events.Details; @@ -53,9 +52,7 @@ import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.AbstractKeycloakTest; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.admin.ApiUtil; -import org.keycloak.testsuite.arquillian.annotation.DisableFeature; import org.keycloak.testsuite.auth.page.AuthRealm; -import org.keycloak.testsuite.pages.AccountApplicationsPage; import org.keycloak.testsuite.pages.LoginPage; import org.keycloak.testsuite.updaters.RealmAttributeUpdater; import org.keycloak.testsuite.util.ClientBuilder; @@ -66,6 +63,7 @@ import org.keycloak.testsuite.util.RealmManager; import org.keycloak.testsuite.util.RoleBuilder; import org.keycloak.testsuite.util.TokenSignatureUtil; import org.keycloak.testsuite.util.UserBuilder; +import org.keycloak.testsuite.util.AccountHelper; import org.keycloak.testsuite.utils.tls.TLSUtils; import org.keycloak.util.TokenUtil; @@ -73,6 +71,8 @@ import javax.ws.rs.NotFoundException; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.LinkedHashMap; +import java.util.ArrayList; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.greaterThanOrEqualTo; @@ -87,6 +87,7 @@ import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; import static org.keycloak.testsuite.admin.ApiUtil.findRealmRoleByName; import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsername; import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsernameId; +import static org.keycloak.testsuite.auth.page.AuthRealm.TEST; import static org.keycloak.testsuite.util.OAuthClient.APP_ROOT; import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot; @@ -105,9 +106,6 @@ public class OfflineTokenTest extends AbstractKeycloakTest { @Page protected LoginPage loginPage; - @Page - protected AccountApplicationsPage applicationsPage; - @Rule public AssertEvents events = new AssertEvents(this); @@ -521,7 +519,6 @@ public class OfflineTokenTest extends AbstractKeycloakTest { // KEYCLOAK-4525 @Test - @DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) public void offlineTokenRemoveClientWithTokens() throws Exception { // Create new client RealmResource appRealm = adminClient.realm("test"); @@ -556,23 +553,26 @@ public class OfflineTokenTest extends AbstractKeycloakTest { .removeDetail(Details.CONSENT) .assertEvent(); - // Go to account mgmt applications page - applicationsPage.open(); - loginPage.login("test-user@localhost", "password"); - events.expectLogin().client("account").detail(Details.REDIRECT_URI, getAccountRedirectUrl() + "?path=applications").assertEvent(); - assertTrue(applicationsPage.isCurrent()); - Map apps = applicationsPage.getApplications(); - assertTrue(apps.containsKey("offline-client-2")); - Assert.assertEquals("Offline Token", apps.get("offline-client-2").getAdditionalGrants().get(0)); + // Confirm that offline-client-2 token was granted + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), "test-user@localhost"); + + String clientId2 = "", offlineAdditionalGrant = ""; + for (Map consent : userConsents) { + if (consent.get("clientId").equals("offline-client-2")) { + clientId2 = String.valueOf(consent.get("clientId")); + offlineAdditionalGrant = String.valueOf(((LinkedHashMap) ((ArrayList) consent.get("additionalGrants")).get(0)).get("key")); + } + } + + assertEquals("offline-client-2", clientId2); + assertEquals("Offline Token", offlineAdditionalGrant); // Now remove the client ClientResource offlineTokenClient2 = ApiUtil.findClientByClientId(appRealm, "offline-client-2" ); offlineTokenClient2.remove(); - // Go to applications page and see offline-client not anymore - applicationsPage.open(); - apps = applicationsPage.getApplications(); - assertFalse(apps.containsKey("offline-client-2")); + // Confirm that offline-client-2 token was deleted + assertNull(ApiUtil.findClientByClientId(appRealm, "offline-client-2")); // Login as admin and see consents of user UserResource user = ApiUtil.findUserByUsernameId(appRealm, "test-user@localhost"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/AbstractOIDCScopeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/AbstractOIDCScopeTest.java index 3cccfae565..9f745c1b2e 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/AbstractOIDCScopeTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/AbstractOIDCScopeTest.java @@ -29,7 +29,6 @@ import org.keycloak.representations.idm.EventRepresentation; import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; import org.keycloak.testsuite.Assert; import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.pages.AccountApplicationsPage; import org.keycloak.testsuite.pages.AccountUpdateProfilePage; import org.keycloak.testsuite.pages.AppPage; import org.keycloak.testsuite.pages.ErrorPage; @@ -57,8 +56,6 @@ public abstract class AbstractOIDCScopeTest extends AbstractTestRealmKeycloakTes @Page protected OAuthGrantPage grantPage; - @Page - protected AccountApplicationsPage accountAppsPage; @Page protected ErrorPage errorPage; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java index c273f0d733..32283ac050 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java @@ -26,7 +26,6 @@ import org.keycloak.admin.client.resource.ClientScopeResource; import org.keycloak.common.Profile; import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.events.Details; -import org.keycloak.events.EventType; import org.keycloak.models.ClientScopeModel; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.protocol.oidc.OIDCLoginProtocol; @@ -50,14 +49,17 @@ import org.keycloak.testsuite.util.ClientManager; import org.keycloak.testsuite.util.OAuthClient; import org.keycloak.testsuite.util.RoleBuilder; import org.keycloak.testsuite.util.UserBuilder; +import org.keycloak.testsuite.util.AccountHelper; import javax.ws.rs.NotFoundException; import javax.ws.rs.core.Response; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; +import static org.keycloak.testsuite.auth.page.AuthRealm.TEST; /** * Test for OAuth2 'scope' parameter and for some other aspects of client scopes @@ -165,7 +167,7 @@ public class OIDCScopeTest extends AbstractOIDCScopeTest { } } - + @Test public void testBuiltinOptionalScopes() throws Exception { // Login. Assert that just 'profile' and 'email' data are there. 'Address' and 'phone' not @@ -502,14 +504,10 @@ public class OIDCScopeTest extends AbstractOIDCScopeTest { .assertEvent(); // Go to applications in account mgmt and revoke consent - accountAppsPage.open(); events.clear(); - accountAppsPage.revokeGrant("third-party"); - events.expect(EventType.REVOKE_GRANT) - .client("account") - .user(userId) - .detail(Details.REVOKED_CLIENT, "third-party") - .assertEvent(); + AccountHelper.revokeConsents(adminClient.realm(TEST), "john", "third-party"); + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), "john"); + Assert.assertEquals(userConsents.size(), 0); // Ensure I can't refresh anymore refreshResponse = oauth.doRefreshTokenRequest(refreshResponse.getRefreshToken(), "password"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AccountHelper.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AccountHelper.java index f034358e00..7d7a00ec56 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AccountHelper.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/AccountHelper.java @@ -18,6 +18,8 @@ package org.keycloak.testsuite.util; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.UserResource; +import java.util.List; +import java.util.Map; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.UserRepresentation; @@ -26,13 +28,7 @@ import java.util.Optional; public class AccountHelper { public static boolean updatePassword(RealmResource realm, String username, String password) { - Optional userResult = realm.users().search(username).stream().findFirst(); - if (userResult.isEmpty()) { - throw new RuntimeException("User with username " + username + " not found"); - } - - UserRepresentation userRepresentation = userResult.get(); - UserResource user = realm.users().get(userRepresentation.getId()); + UserResource user = realm.users().get(getUserId(realm, username)); CredentialRepresentation credentialRepresentation = CredentialBuilder.create().password(password).build(); @@ -44,4 +40,30 @@ public class AccountHelper { } } + public static List> getUserConsents(RealmResource realm, String username) { + UserResource user = realm.users().get(getUserId(realm, username)); + List> consents = user.getConsents(); + return consents; + } + + public static void revokeConsents(RealmResource realm, String username, String clientId) { + UserResource user = realm.users().get(getUserId(realm, username)); + user.revokeConsent(clientId); + } + + public static void logout(RealmResource realm, String username) { + UserResource user = realm.users().get(getUserId(realm, username)); + user.logout(); + } + + private static String getUserId(RealmResource realm, String username) { + Optional userResult = realm.users().search(username).stream().findFirst(); + if (userResult.isEmpty()) { + throw new RuntimeException("User with username " + username + " not found"); + } + + UserRepresentation userRepresentation = userResult.get(); + return userRepresentation.getId(); + } + } diff --git a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/OfflineTokenSpringBootTest.java b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/OfflineTokenSpringBootTest.java index f9f332ec89..7ab1d48205 100644 --- a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/OfflineTokenSpringBootTest.java +++ b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/OfflineTokenSpringBootTest.java @@ -16,15 +16,18 @@ import org.keycloak.services.Urls; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.arquillian.annotation.DisableFeature; -import org.keycloak.testsuite.pages.AccountApplicationsPage; import org.keycloak.testsuite.pages.OAuthGrantPage; import org.keycloak.testsuite.util.ClientManager; import org.keycloak.testsuite.util.WaitUtils; +import org.keycloak.testsuite.util.AccountHelper; import org.keycloak.util.TokenUtil; import org.openqa.selenium.By; import javax.ws.rs.core.UriBuilder; import java.util.List; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.ArrayList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasItem; @@ -37,16 +40,13 @@ import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; import static org.keycloak.testsuite.util.WaitUtils.pause; import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad; -@DisableFeature(value = Profile.Feature.ACCOUNT2, skipRestart = true) // TODO remove this (KEYCLOAK-16228) public class OfflineTokenSpringBootTest extends AbstractSpringBootTest { private static final String SERVLET_URL = BASE_URL + "/TokenServlet"; + private final String TEST_REALM = "test"; @Rule public AssertEvents events = new AssertEvents(this); - @Page - private AccountApplicationsPage accountAppPage; - @Page private OAuthGrantPage oauthGrantPage; @@ -118,24 +118,19 @@ public class OfflineTokenSpringBootTest extends AbstractSpringBootTest { events.clear(); // Go to account service and revoke grant - accountAppPage.open(); - waitForPageToLoad(); + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST_REALM), USER_LOGIN); + String grantValue = String.valueOf(((LinkedHashMap) ((ArrayList) userConsents.get(0).get("additionalGrants")).get(0)).get("key")); + assertThat(userConsents, hasSize(1)); + Assert.assertEquals("Offline Token", grantValue); - List additionalGrants = accountAppPage.getApplications().get(CLIENT_ID).getAdditionalGrants(); - assertThat(additionalGrants, hasSize(1)); - assertThat(additionalGrants, hasItem("Offline Token")); - - accountAppPage.revokeGrant(CLIENT_ID); - - assertThat(accountAppPage.getApplications().get(CLIENT_ID).getAdditionalGrants(), hasSize(0)); + AccountHelper.revokeConsents(adminClient.realm(TEST_REALM), USER_LOGIN, CLIENT_ID); + userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST_REALM), USER_LOGIN); + Assert.assertEquals(userConsents.size(), 0); UserRepresentation userRepresentation = ApiUtil.findUserByUsername(realmsResouce().realm(REALM_NAME), USER_LOGIN); assertThat(userRepresentation, is(notNullValue())); - events.expect(EventType.REVOKE_GRANT).realm(REALM_ID).user(userRepresentation.getId()) - .client("account").detail(Details.REVOKED_CLIENT, CLIENT_ID).assertEvent(); - // Assert refresh doesn't work now (increase time one more time) setAdapterAndServerTimeOffset(19999, SERVLET_URL); driver.navigate().to(SERVLET_URL); @@ -173,14 +168,10 @@ public class OfflineTokenSpringBootTest extends AbstractSpringBootTest { tokenPage.assertIsCurrent(); assertThat(tokenPage.getRefreshToken().getType(), is(equalTo(TokenUtil.TOKEN_TYPE_OFFLINE))); - String accountAppPageUrl = - Urls.accountApplicationsPage(getAuthServerRoot(), REALM_NAME).toString(); - driver.navigate().to(accountAppPageUrl); - waitForPageToLoad(); - - AccountApplicationsPage.AppEntry offlineClient = accountAppPage.getApplications().get(CLIENT_ID); - assertThat(offlineClient.getClientScopesGranted(), hasItem(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT)); - assertThat(offlineClient.getAdditionalGrants(), hasItem("Offline Token")); + List> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST_REALM), USER_LOGIN); + String grantValue = String.valueOf(((LinkedHashMap) ((ArrayList) userConsents.get(0).get("additionalGrants")).get(0)).get("key")); + Assert.assertTrue(((List) userConsents.get(0).get("grantedClientScopes")).stream().anyMatch(p -> p.equals("offline_access"))); + Assert.assertEquals("Offline Token", grantValue); //This was necessary to be introduced, otherwise other testcases will fail logout(SERVLET_URL);