Removes AccountApplicationsPage (#17651)

Closes #15198 


Co-authored-by: wojnarfilip <fwojnar@redhat.com>
This commit is contained in:
fwojnar 2023-04-05 16:54:16 +02:00 committed by GitHub
parent 783cf00f3e
commit f55794f8bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 152 additions and 327 deletions

View File

@ -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 <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
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<String, AppEntry> getApplications() {
Map<String, AppEntry> table = new HashMap<String, AppEntry>();
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<String> rolesAvailable = new ArrayList<String>();
private final List<String> clientScopesGranted = new ArrayList<String>();
private final List<String> 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<String> getRolesAvailable() {
return rolesAvailable;
}
public List<String> getClientScopesGranted() {
return clientScopesGranted;
}
public List<String> getAdditionalGrants() {
return additionalGrants;
}
}
}

View File

@ -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<Map<String, Object>> 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<String> 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<Map<String, Object>> 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);
}
}

View File

@ -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;

View File

@ -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 <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
*/
@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<Map<String, Object>> 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<Map<String, Object>> 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<Map<String, Object>> 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<String> 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<Map<String, Object>> 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<String> 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<Map<String, Object>> 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<String, AccountApplicationsPage.AppEntry> apps = accountAppsPage.getApplications();
Assert.assertTrue(apps.containsKey("third-party"));
Assert.assertTrue(apps.get("third-party").getClientScopesGranted().contains("foo-addr"));
List<Map<String, Object>> 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<String> 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();

View File

@ -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<String, AccountApplicationsPage.AppEntry> 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<Map<String, Object>> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), "test-user@localhost");
String clientId2 = "", offlineAdditionalGrant = "";
for (Map<String, Object> 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");

View File

@ -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;

View File

@ -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<Map<String, Object>> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), "john");
Assert.assertEquals(userConsents.size(), 0);
// Ensure I can't refresh anymore
refreshResponse = oauth.doRefreshTokenRequest(refreshResponse.getRefreshToken(), "password");

View File

@ -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<UserRepresentation> 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<Map<String, Object>> getUserConsents(RealmResource realm, String username) {
UserResource user = realm.users().get(getUserId(realm, username));
List<Map<String, Object>> 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<UserRepresentation> 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();
}
}

View File

@ -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<Map<String, Object>> 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<String> 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<Map<String, Object>> 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);