keycloak-uncached
Changes
services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java 31(+18 -13)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ClientAttributeUpdater.java 63(+48 -15)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RealmAttributeUpdater.java 29(+8 -21)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RoleScopeUpdater.java 63(+63 -0)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ServerResourceUpdater.java 112(+112 -0)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/UserAttributeUpdater.java 40(+25 -15)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java 67(+59 -8)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/OfflineServletsAdapterTest.java 5(+3 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java 9(+3 -6)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java 20(+2 -18)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java 5(+1 -4)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java 4(+1 -3)
Details
diff --git a/server-spi/src/main/java/org/keycloak/models/OrderedModel.java b/server-spi/src/main/java/org/keycloak/models/OrderedModel.java
index 3134ea5..603e7a5 100644
--- a/server-spi/src/main/java/org/keycloak/models/OrderedModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/OrderedModel.java
@@ -29,6 +29,13 @@ public interface OrderedModel {
class OrderedModelComparator<OM extends OrderedModel> implements Comparator<OM> {
+ public static final OrderedModelComparator INSTANCE = new OrderedModelComparator();
+
+ @SuppressWarnings("unchecked")
+ public static <T extends OrderedModel> OrderedModelComparator<T> getInstance() {
+ return INSTANCE;
+ }
+
@Override
public int compare(OM o1, OM o2) {
int o1order = parseOrder(o1);
diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java b/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java
index 3a5aa86..baaa525 100755
--- a/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java
+++ b/services/src/main/java/org/keycloak/forms/account/freemarker/model/ApplicationsBean.java
@@ -18,13 +18,11 @@
package org.keycloak.forms.account.freemarker.model;
import org.keycloak.common.util.MultivaluedHashMap;
-import org.keycloak.forms.login.freemarker.model.OAuthGrantBean;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OrderedModel;
-import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserConsentModel;
@@ -39,7 +37,6 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-import java.util.TreeSet;
import java.util.stream.Collectors;
/**
@@ -47,36 +44,44 @@ import java.util.stream.Collectors;
*/
public class ApplicationsBean {
- private List<ApplicationEntry> applications = new LinkedList<ApplicationEntry>();
+ private List<ApplicationEntry> applications = new LinkedList<>();
public ApplicationsBean(KeycloakSession session, RealmModel realm, UserModel user) {
Set<ClientModel> offlineClients = new UserSessionManager(session).findClientsWithOfflineToken(realm, user);
for (ClientModel client : getApplications(session, realm, user)) {
- Set<RoleModel> availableRoles = new HashSet<>();
+ if (isAdminClient(client) && ! AdminPermissions.realms(session, realm, user).isAdmin()) {
+ continue;
+ }
// Construct scope parameter with all optional scopes to see all potentially available roles
Set<ClientScopeModel> allClientScopes = new HashSet<>(client.getClientScopes(true, true).values());
allClientScopes.addAll(client.getClientScopes(false, true).values());
allClientScopes.add(client);
- availableRoles = TokenManager.getAccess(user, client, allClientScopes);
+ Set<RoleModel> availableRoles = TokenManager.getAccess(user, client, allClientScopes);
+
+ // Don't show applications, which user doesn't have access into (any available roles)
+ // unless this is can be changed by approving/revoking consent
+ if (! isAdminClient(client) && availableRoles.isEmpty() && ! client.isConsentRequired()) {
+ continue;
+ }
List<RoleModel> realmRolesAvailable = new LinkedList<>();
MultivaluedHashMap<String, ClientRoleEntry> resourceRolesAvailable = new MultivaluedHashMap<>();
processRoles(availableRoles, realmRolesAvailable, resourceRolesAvailable);
- List<ClientScopeModel> orderedScopes = new ArrayList<>();
+ List<ClientScopeModel> orderedScopes = new LinkedList<>();
if (client.isConsentRequired()) {
UserConsentModel consent = session.users().getConsentByClient(realm, user.getId(), client.getId());
if (consent != null) {
orderedScopes.addAll(consent.getGrantedClientScopes());
- orderedScopes.sort(new OrderedModel.OrderedModelComparator<>());
}
}
List<String> clientScopesGranted = orderedScopes.stream()
+ .sorted(OrderedModel.OrderedModelComparator.getInstance())
.map(ClientScopeModel::getConsentScreenText)
.collect(Collectors.toList());
@@ -89,6 +94,11 @@ public class ApplicationsBean {
}
}
+ public static boolean isAdminClient(ClientModel client) {
+ return client.getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)
+ || client.getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID);
+ }
+
private Set<ClientModel> getApplications(KeycloakSession session, RealmModel realm, UserModel user) {
Set<ClientModel> clients = new HashSet<>();
@@ -98,11 +108,6 @@ public class ApplicationsBean {
continue;
}
- if (client.getClientId().equals(Constants.ADMIN_CLI_CLIENT_ID)
- || client.getClientId().equals(Constants.ADMIN_CONSOLE_CLIENT_ID)) {
- if (!AdminPermissions.realms(session, realm, user).isAdmin()) continue;
- }
-
clients.add(client);
}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ClientAttributeUpdater.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ClientAttributeUpdater.java
index 106aa5b..0445b5e 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ClientAttributeUpdater.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ClientAttributeUpdater.java
@@ -3,10 +3,14 @@ package org.keycloak.testsuite.updaters;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.ClientsResource;
+import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.representations.idm.ClientRepresentation;
-import java.io.Closeable;
+import org.keycloak.representations.idm.ClientScopeRepresentation;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;
@@ -14,29 +18,40 @@ import static org.junit.Assert.assertThat;
*
* @author hmlnarik
*/
-public class ClientAttributeUpdater {
+public class ClientAttributeUpdater extends ServerResourceUpdater<ClientAttributeUpdater, ClientResource, ClientRepresentation> {
- private final ClientResource clientResource;
-
- private final ClientRepresentation rep;
- private final ClientRepresentation origRep;
+ private final RealmResource realmResource;
public static ClientAttributeUpdater forClient(Keycloak adminClient, String realm, String clientId) {
- ClientsResource clients = adminClient.realm(realm).clients();
+ RealmResource realmRes = adminClient.realm(realm);
+ ClientsResource clients = realmRes.clients();
List<ClientRepresentation> foundClients = clients.findByClientId(clientId);
assertThat(foundClients, hasSize(1));
ClientResource clientRes = clients.get(foundClients.get(0).getId());
- return new ClientAttributeUpdater(clientRes);
+ return new ClientAttributeUpdater(clientRes, realmRes);
}
- public ClientAttributeUpdater(ClientResource clientResource) {
- this.clientResource = clientResource;
- this.origRep = clientResource.toRepresentation();
- this.rep = clientResource.toRepresentation();
+ private ClientAttributeUpdater(ClientResource resource, RealmResource realmResource) {
+ super(resource, resource::toRepresentation, resource::update);
if (this.rep.getAttributes() == null) {
this.rep.setAttributes(new HashMap<>());
}
+ this.realmResource = realmResource;
+ }
+
+ @Override
+ protected void performUpdate(ClientRepresentation from, ClientRepresentation to) {
+ super.performUpdate(from, to);
+ updateViaAddRemove(from.getDefaultClientScopes(), to.getDefaultClientScopes(), this::getConversionForScopeNameToId, resource::addDefaultClientScope, resource::removeDefaultClientScope);
+ updateViaAddRemove(from.getOptionalClientScopes(), to.getOptionalClientScopes(), this::getConversionForScopeNameToId, resource::addOptionalClientScope, resource::removeOptionalClientScope);
+ }
+
+ private Function<String, String> getConversionForScopeNameToId() {
+ Map<String, String> scopeNameToIdMap = realmResource.clientScopes().findAll().stream()
+ .collect(Collectors.toMap(ClientScopeRepresentation::getName, ClientScopeRepresentation::getId));
+
+ return scopeNameToIdMap::get;
}
public ClientAttributeUpdater setClientId(String clientId) {
@@ -64,9 +79,27 @@ public class ClientAttributeUpdater {
return this;
}
- public Closeable update() {
- clientResource.update(rep);
+ public ClientAttributeUpdater setFullScopeAllowed(Boolean fullScopeAllowed) {
+ rep.setFullScopeAllowed(fullScopeAllowed);
+ return this;
+ }
- return () -> clientResource.update(origRep);
+ public ClientAttributeUpdater setDefaultClientScopes(List<String> defaultClientScopes) {
+ rep.setDefaultClientScopes(defaultClientScopes);
+ return this;
}
+
+ public ClientAttributeUpdater setOptionalClientScopes(List<String> optionalClientScopes) {
+ rep.setOptionalClientScopes(optionalClientScopes);
+ return this;
+ }
+
+ public RoleScopeUpdater realmRoleScope() {
+ return new RoleScopeUpdater(resource.getScopeMappings().realmLevel());
+ }
+
+ public RoleScopeUpdater clientRoleScope(String clientUUID) {
+ return new RoleScopeUpdater(resource.getScopeMappings().clientLevel(clientUUID));
+ }
+
}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RealmAttributeUpdater.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RealmAttributeUpdater.java
index 1b9df30..fad4f9a 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RealmAttributeUpdater.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RealmAttributeUpdater.java
@@ -2,35 +2,22 @@ package org.keycloak.testsuite.updaters;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.representations.idm.RealmRepresentation;
-import java.io.Closeable;
import java.util.HashMap;
-import java.util.function.Consumer;
+import java.util.List;
/**
*
* @author hmlnarik
*/
-public class RealmAttributeUpdater {
+public class RealmAttributeUpdater extends ServerResourceUpdater<ServerResourceUpdater, RealmResource, RealmRepresentation> {
- private final RealmResource realmResource;
-
- private final RealmRepresentation rep;
- private final RealmRepresentation origRep;
-
- public RealmAttributeUpdater(RealmResource realmResource) {
- this.realmResource = realmResource;
- this.origRep = realmResource.toRepresentation();
- this.rep = realmResource.toRepresentation();
+ public RealmAttributeUpdater(RealmResource resource) {
+ super(resource, resource::toRepresentation, resource::update);
if (this.rep.getAttributes() == null) {
this.rep.setAttributes(new HashMap<>());
}
}
- public RealmAttributeUpdater updateWith(Consumer<RealmRepresentation> updater) {
- updater.accept(this.rep);
- return this;
- }
-
public RealmAttributeUpdater setAttribute(String name, String value) {
this.rep.getAttributes().put(name, value);
return this;
@@ -51,9 +38,9 @@ public class RealmAttributeUpdater {
return this;
}
- public Closeable update() {
- realmResource.update(rep);
-
- return () -> realmResource.update(origRep);
+ public RealmAttributeUpdater setDefaultDefaultClientScopes(List<String> defaultClientScopes) {
+ rep.setDefaultDefaultClientScopes(defaultClientScopes);
+ return this;
}
+
}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RoleScopeUpdater.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RoleScopeUpdater.java
new file mode 100644
index 0000000..dd295b0
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/RoleScopeUpdater.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 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.updaters;
+
+import org.keycloak.admin.client.resource.RoleScopeResource;
+import org.keycloak.representations.idm.RoleRepresentation;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * @author hmlnarik
+ */
+public class RoleScopeUpdater extends ServerResourceUpdater<RoleScopeUpdater, RoleScopeResource, List<RoleRepresentation>> {
+
+ public RoleScopeUpdater(RoleScopeResource resource) {
+ super(resource, resource::listAll, null);
+ this.updater = this::update;
+ }
+
+ public RoleScopeUpdater add(RoleRepresentation representation) {
+ rep.add(representation);
+ return this;
+ }
+
+ public RoleScopeUpdater remove(RoleRepresentation representation) {
+ rep.add(representation);
+ return this;
+ }
+
+ private void update(List<RoleRepresentation> expectedRoles) {
+ List<RoleRepresentation> currentRoles = resource.listAll();
+
+ Set<String> currentRoleIds = currentRoles.stream().map(RoleRepresentation::getId).collect(Collectors.toSet());
+ Set<String> expectedRoleIds = expectedRoles.stream().map(RoleRepresentation::getId).collect(Collectors.toSet());
+
+ List<RoleRepresentation> toAdd = expectedRoles.stream()
+ .filter(role -> ! currentRoleIds.contains(role.getId()))
+ .collect(Collectors.toList());
+ List<RoleRepresentation> toRemove = currentRoles.stream()
+ .filter(role -> ! expectedRoleIds.contains(role.getId()))
+ .collect(Collectors.toList());
+
+ resource.add(toAdd);
+ resource.remove(toRemove);
+ }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ServerResourceUpdater.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ServerResourceUpdater.java
new file mode 100644
index 0000000..d8d0621
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/ServerResourceUpdater.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2018 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.updaters;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+/**
+ *
+ * @author hmlnarik
+ */
+public abstract class ServerResourceUpdater<T extends ServerResourceUpdater, Res, Rep> implements Closeable {
+
+ protected final Res resource;
+ protected final Rep rep;
+ protected final Rep origRep;
+ protected Consumer<Rep> updater;
+ protected boolean updated = false;
+
+ public ServerResourceUpdater(Res resource, Supplier<Rep> representationGenerator, Consumer<Rep> updater) {
+ this.resource = resource;
+ this.updater = updater;
+
+ // origRep and rep need to be two different instances
+ this.origRep = representationGenerator.get();
+ this.rep = representationGenerator.get();
+ }
+
+ public Res getResource() {
+ return resource;
+ }
+
+ public T update() {
+ performUpdate(origRep, rep);
+ this.updated = true;
+ return (T) this;
+ }
+
+ protected void performUpdate(Rep from, Rep to) {
+ updater.accept(to);
+ }
+
+ public T updateWith(Consumer<Rep> representationUpdater) {
+ representationUpdater.accept(this.rep);
+ return (T) this;
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (! this.updated) {
+ throw new IOException("Attempt to revert changes that were never applied - have you called " + this.getClass().getName() + ".update()?");
+ }
+ performUpdate(rep, origRep);
+ }
+
+ /**
+ * This function performs a set of single {@code add} and {@code remove} operations that represent the changes needed to
+ * get collection {@code from} to the state of collection {@code to}. Since this is intended to work on collections of
+ * names of objects but the {@code add} and {@code remove} functions operate on IDs of those objects, a conversion
+ * is performed.
+ *
+ * @param <T> Type of the objects in the collections (e.g. names)
+ * @param <V> Type of the objects required by add/remove functions (e.g. IDs)
+ * @param from Initial collection
+ * @param to Target collection
+ * @param client2ServerConvertorGenerator Producer of the convertor. If not needed, just use {@code () -> Functions::identity}.
+ * This is intentionally a lazy-evaluated function variable because the conversion map often needs to be obtained from the
+ * server which can be slow operation. This function is called only if the two collections differ.
+ * @param add Function to add
+ * @param remove Function to remove
+ */
+ public static <T, V> void updateViaAddRemove(Collection<T> from, Collection<T> to, Supplier<Function<T, V>> client2ServerConvertorGenerator, Consumer<V> add, Consumer<V> remove) {
+ if (Objects.equals(from, to)) {
+ return;
+ }
+
+ Function<T, V> client2ServerConvertor = client2ServerConvertorGenerator.get();
+
+ Set<V> current = from == null ? Collections.EMPTY_SET : from.stream().map(client2ServerConvertor).collect(Collectors.toSet());
+ Set<V> expected = to == null ? Collections.EMPTY_SET : to.stream().map(client2ServerConvertor).collect(Collectors.toSet());
+
+ expected.stream()
+ .filter(role -> ! current.contains(role))
+ .forEach(add);
+ current.stream()
+ .filter(role -> ! expected.contains(role))
+ .forEach(remove);
+ }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/UserAttributeUpdater.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/UserAttributeUpdater.java
index be1182a..9603dad 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/UserAttributeUpdater.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/updaters/UserAttributeUpdater.java
@@ -1,29 +1,37 @@
package org.keycloak.testsuite.updaters;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.ClientsResource;
import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.models.UserModel;
+import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
-import java.io.Closeable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertThat;
/**
*
* @author hmlnarik
*/
-public class UserAttributeUpdater {
+public class UserAttributeUpdater extends ServerResourceUpdater<UserAttributeUpdater, UserResource, UserRepresentation> {
- private final UserResource userResource;
+ public static UserAttributeUpdater forUserByUsername(Keycloak adminClient, String realm, String userName) {
+ UsersResource users = adminClient.realm(realm).users();
+ List<UserRepresentation> foundUsers = users.search(userName);
+ assertThat(foundUsers, hasSize(1));
+ UserResource userRes = users.get(foundUsers.get(0).getId());
- private final UserRepresentation rep;
- private final UserRepresentation origRep;
+ return new UserAttributeUpdater(userRes);
+ }
- public UserAttributeUpdater(UserResource userResource) {
- this.userResource = userResource;
- this.origRep = userResource.toRepresentation();
- this.rep = userResource.toRepresentation();
+ public UserAttributeUpdater(UserResource resource) {
+ super(resource, resource::toRepresentation, resource::update);
if (this.rep.getAttributes() == null) {
this.rep.setAttributes(new HashMap<>());
}
@@ -49,12 +57,6 @@ public class UserAttributeUpdater {
return this;
}
- public Closeable update() {
- userResource.update(rep);
-
- return () -> userResource.update(origRep);
- }
-
public UserAttributeUpdater setRequiredActions(UserModel.RequiredAction... requiredAction) {
rep.setRequiredActions(Arrays.stream(requiredAction)
.map(action -> action.name())
@@ -62,4 +64,12 @@ public class UserAttributeUpdater {
);
return this;
}
+
+ public RoleScopeUpdater realmRoleScope() {
+ return new RoleScopeUpdater(resource.roles().realmLevel());
+ }
+
+ public RoleScopeUpdater clientRoleScope(String clientUUID) {
+ return new RoleScopeUpdater(resource.roles().clientLevel(clientUUID));
+ }
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java
index cfae103..755a042 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/account/AccountFormServiceTest.java
@@ -57,11 +57,16 @@ import org.keycloak.testsuite.pages.AppPage.RequestType;
import org.keycloak.testsuite.pages.ErrorPage;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.RegisterPage;
+import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
+import org.keycloak.testsuite.updaters.RoleScopeUpdater;
import org.keycloak.testsuite.util.IdentityProviderBuilder;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.RealmBuilder;
import org.keycloak.testsuite.util.UIUtils;
import org.keycloak.testsuite.util.UserBuilder;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collections;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
@@ -86,6 +91,9 @@ import static org.junit.Assert.assertTrue;
*/
public class AccountFormServiceTest extends AbstractTestRealmKeycloakTest {
+ public static final String ROOT_URL_CLIENT = "root-url-client";
+ public static final String REALM_NAME = "test";
+
@Override
public void configureTestRealm(RealmRepresentation testRealm) {
//UserRepresentation user = findUserInRealmRep(testRealm, "test-user@localhost");
@@ -1067,7 +1075,50 @@ public class AccountFormServiceTest extends AbstractTestRealmKeycloakTest {
events.clear();
}
+ @Test
+ public void applicationsVisibilityNoScopesNoConsent() throws Exception {
+ try (ClientAttributeUpdater cau = ClientAttributeUpdater.forClient(adminClient, REALM_NAME, ROOT_URL_CLIENT)
+ .setConsentRequired(false)
+ .setFullScopeAllowed(false)
+ .setDefaultClientScopes(Collections.EMPTY_LIST)
+ .setOptionalClientScopes(Collections.EMPTY_LIST)
+ .update();
+ RoleScopeUpdater rsu = cau.realmRoleScope().update()) {
+ applicationsPage.open();
+ loginPage.login("john-doh@localhost", "password");
+ applicationsPage.assertCurrent();
+
+ Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
+ Assert.assertThat(apps.keySet(), containsInAnyOrder(
+ /* "root-url-client", */ "Account", "test-app", "test-app-scope", "third-party", "test-app-authz", "My Named Test App", "Test App Named - ${client_account}", "direct-grant"));
+
+ rsu.add(testRealm().roles().get("user").toRepresentation())
+ .update();
+
+ driver.navigate().refresh();
+ apps = applicationsPage.getApplications();
+ Assert.assertThat(apps.keySet(), containsInAnyOrder(
+ "root-url-client", "Account", "test-app", "test-app-scope", "third-party", "test-app-authz", "My Named Test App", "Test App Named - ${client_account}", "direct-grant"));
+ }
+ }
+ @Test
+ public void applicationsVisibilityNoScopesAndConsent() throws Exception {
+ try (ClientAttributeUpdater cau = ClientAttributeUpdater.forClient(adminClient, REALM_NAME, ROOT_URL_CLIENT)
+ .setConsentRequired(true)
+ .setFullScopeAllowed(false)
+ .setDefaultClientScopes(Collections.EMPTY_LIST)
+ .setOptionalClientScopes(Collections.EMPTY_LIST)
+ .update()) {
+ applicationsPage.open();
+ loginPage.login("john-doh@localhost", "password");
+ applicationsPage.assertCurrent();
+
+ Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
+ Assert.assertThat(apps.keySet(), containsInAnyOrder(
+ "root-url-client", "Account", "test-app", "test-app-scope", "third-party", "test-app-authz", "My Named Test App", "Test App Named - ${client_account}", "direct-grant"));
+ }
+ }
// More tests (including revoke) are in OAuthGrantTest and OfflineTokenTest
@Test
@@ -1076,19 +1127,19 @@ public class AccountFormServiceTest extends AbstractTestRealmKeycloakTest {
loginPage.login("test-user@localhost", "password");
events.expectLogin().client("account").detail(Details.REDIRECT_URI, ACCOUNT_REDIRECT + "?path=applications").assertEvent();
- Assert.assertTrue(applicationsPage.isCurrent());
+ applicationsPage.assertCurrent();
Map<String, AccountApplicationsPage.AppEntry> apps = applicationsPage.getApplications();
Assert.assertThat(apps.keySet(), containsInAnyOrder("root-url-client", "Account", "Broker", "test-app", "test-app-scope", "third-party", "test-app-authz", "My Named Test App", "Test App Named - ${client_account}", "direct-grant"));
AccountApplicationsPage.AppEntry accountEntry = apps.get("Account");
- Assert.assertEquals(4, accountEntry.getRolesAvailable().size());
- Assert.assertTrue(accountEntry.getRolesAvailable().contains("Manage account links in Account"));
- Assert.assertTrue(accountEntry.getRolesAvailable().contains("Manage account in Account"));
- Assert.assertTrue(accountEntry.getRolesAvailable().contains("View profile in Account"));
- Assert.assertTrue(accountEntry.getRolesAvailable().contains("Offline access"));
- Assert.assertEquals(1, accountEntry.getClientScopesGranted().size());
- Assert.assertTrue(accountEntry.getClientScopesGranted().contains("Full Access"));
+ Assert.assertThat(accountEntry.getRolesAvailable(), containsInAnyOrder(
+ "Manage account links in Account",
+ "Manage account in Account",
+ "View profile in Account",
+ "Offline access"
+ ));
+ Assert.assertThat(accountEntry.getClientScopesGranted(), containsInAnyOrder("Full Access"));
Assert.assertEquals("http://localhost:8180/auth/realms/test/account", accountEntry.getHref());
AccountApplicationsPage.AppEntry testAppEntry = apps.get("test-app");
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 e278e96..58fca76 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
@@ -24,6 +24,7 @@ import org.keycloak.testsuite.pages.OAuthGrantPage;
import org.keycloak.testsuite.util.ClientManager;
import org.keycloak.testsuite.utils.io.IOUtil;
import org.keycloak.util.TokenUtil;
+import org.hamcrest.Matchers;
import org.openqa.selenium.By;
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
@@ -181,8 +182,8 @@ public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest {
accountAppPage.open();
AccountApplicationsPage.AppEntry offlineClient = accountAppPage.getApplications().get("offline-client");
- Assert.assertTrue(offlineClient.getClientScopesGranted().contains(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT));
- Assert.assertTrue(offlineClient.getAdditionalGrants().contains("Offline Token"));
+ Assert.assertThat(offlineClient.getClientScopesGranted(), Matchers.hasItem(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT));
+ Assert.assertThat(offlineClient.getAdditionalGrants(), Matchers.hasItem("Offline Token"));
//This was necessary to be introduced, otherwise other testcases will fail
offlineTokenPage.logout();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java
index 431efb4..1d59eed 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/SAMLServletAdapterTest.java
@@ -818,8 +818,7 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
@Test
public void salesPostEncSignedAssertionsAndDocumentTest() throws Exception {
- ClientRepresentation salesPostEncClient = testRealmResource().clients().findByClientId(SalesPostEncServlet.CLIENT_NAME).get(0);
- try (Closeable client = new ClientAttributeUpdater(testRealmResource().clients().get(salesPostEncClient.getId()))
+ try (Closeable client = ClientAttributeUpdater.forClient(adminClient, testRealmPage.getAuthRealm(), SalesPostEncServlet.CLIENT_NAME)
.setAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE, "true")
.setAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE, "true")
.update()) {
@@ -831,8 +830,7 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
@Test
public void salesPostEncRejectConsent() throws Exception {
- ClientRepresentation salesPostEncClient = testRealmResource().clients().findByClientId(SalesPostEncServlet.CLIENT_NAME).get(0);
- try (Closeable client = new ClientAttributeUpdater(testRealmResource().clients().get(salesPostEncClient.getId()))
+ try (Closeable client = ClientAttributeUpdater.forClient(adminClient, testRealmPage.getAuthRealm(), SalesPostEncServlet.CLIENT_NAME)
.setConsentRequired(true)
.update()) {
new SamlClientBuilder()
@@ -853,8 +851,7 @@ public class SAMLServletAdapterTest extends AbstractServletsAdapterTest {
@Test
public void salesPostRejectConsent() throws Exception {
- ClientRepresentation salesPostClient = testRealmResource().clients().findByClientId(SalesPostServlet.CLIENT_NAME).get(0);
- try (Closeable client = new ClientAttributeUpdater(testRealmResource().clients().get(salesPostClient.getId()))
+ try (Closeable client = ClientAttributeUpdater.forClient(adminClient, testRealmPage.getAuthRealm(), SalesPostServlet.CLIENT_NAME)
.setConsentRequired(true)
.update()) {
new SamlClientBuilder()
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java
index 486a4e5..b8e7d24 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcSamlSignedBrokerTest.java
@@ -117,14 +117,6 @@ public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
}
public void withSignedEncryptedAssertions(Runnable testBody, boolean signedAssertion, boolean encryptedAssertion) throws Exception {
- ClientRepresentation client = adminClient.realm(bc.providerRealmName())
- .clients()
- .findByClientId(bc.getIDPClientIdInProviderRealm(suiteContext))
- .get(0);
-
- final ClientResource clientResource = realmsResouce().realm(bc.providerRealmName()).clients().get(client.getId());
- Assert.assertThat(clientResource, Matchers.notNullValue());
-
String providerCert = KeyUtils.getActiveKey(adminClient.realm(bc.providerRealmName()).keys().getKeyMetadata(), Algorithm.RS256).getCertificate();
Assert.assertThat(providerCert, Matchers.notNullValue());
@@ -138,7 +130,7 @@ public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
.setAttribute(SAMLIdentityProviderConfig.WANT_AUTHN_REQUESTS_SIGNED, "false")
.setAttribute(SAMLIdentityProviderConfig.SIGNING_CERTIFICATE_KEY, providerCert)
.update();
- Closeable clientUpdater = new ClientAttributeUpdater(clientResource)
+ Closeable clientUpdater = ClientAttributeUpdater.forClient(adminClient, bc.providerRealmName(), bc.getIDPClientIdInProviderRealm(suiteContext))
.setAttribute(SamlConfigAttributes.SAML_ENCRYPT, Boolean.toString(encryptedAssertion))
.setAttribute(SamlConfigAttributes.SAML_ENCRYPTION_CERTIFICATE_ATTRIBUTE, consumerCert)
.setAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE, "false") // only sign assertions
@@ -269,14 +261,6 @@ public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
@Test
public void testWithExpiredBrokerCertificate() throws Exception {
- ClientRepresentation client = adminClient.realm(bc.providerRealmName())
- .clients()
- .findByClientId(bc.getIDPClientIdInProviderRealm(suiteContext))
- .get(0);
-
- final ClientResource clientResource = realmsResouce().realm(bc.providerRealmName()).clients().get(client.getId());
- Assert.assertThat(clientResource, Matchers.notNullValue());
-
try (Closeable idpUpdater = new IdentityProviderAttributeUpdater(identityProviderResource)
.setAttribute(SAMLIdentityProviderConfig.VALIDATE_SIGNATURE, Boolean.toString(true))
.setAttribute(SAMLIdentityProviderConfig.WANT_ASSERTIONS_SIGNED, Boolean.toString(true))
@@ -284,7 +268,7 @@ public class KcSamlSignedBrokerTest extends KcSamlBrokerTest {
.setAttribute(SAMLIdentityProviderConfig.WANT_AUTHN_REQUESTS_SIGNED, "true")
.setAttribute(SAMLIdentityProviderConfig.SIGNING_CERTIFICATE_KEY, AbstractSamlTest.SAML_CLIENT_SALES_POST_SIG_EXPIRED_CERTIFICATE)
.update();
- Closeable clientUpdater = new ClientAttributeUpdater(clientResource)
+ Closeable clientUpdater = ClientAttributeUpdater.forClient(adminClient, bc.providerRealmName(), bc.getIDPClientIdInProviderRealm(suiteContext))
.setAttribute(SamlConfigAttributes.SAML_ENCRYPT, Boolean.toString(false))
.setAttribute(SamlConfigAttributes.SAML_SERVER_SIGNATURE, "true")
.setAttribute(SamlConfigAttributes.SAML_ASSERTION_SIGNATURE, Boolean.toString(true))
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java
index 54e0714..a4b29f1 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LogoutTest.java
@@ -244,11 +244,8 @@ public class LogoutTest extends AbstractTestRealmKeycloakTest {
// KEYCLOAK-5982
@Test
public void testLogoutWhenAccountClientRenamed() throws IOException {
- // Rename client "account"
- ClientResource accountClient = ApiUtil.findClientByClientId(adminClient.realm("test"), Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-
// Temporarily rename client "account" . Revert it back after the test
- try (Closeable accountClientUpdater = new ClientAttributeUpdater(accountClient)
+ try (Closeable accountClientUpdater = ClientAttributeUpdater.forClient(adminClient, "test", Constants.ACCOUNT_MANAGEMENT_CLIENT_ID)
.setClientId("account-changed")
.update()) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
index 5f36170..2774b15 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
@@ -1011,10 +1011,8 @@ public class ResetPasswordTest extends AbstractTestRealmKeycloakTest {
// KEYCLOAK-5982
@Test
public void resetPasswordLinkOpenedInNewBrowserAndAccountClientRenamed() throws IOException, MessagingException {
- ClientResource accountClient = ApiUtil.findClientByClientId(adminClient.realm("test"), Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
-
// Temporarily rename client "account" . Revert it back after the test
- try (Closeable accountClientUpdater = new ClientAttributeUpdater(accountClient)
+ try (Closeable accountClientUpdater = ClientAttributeUpdater.forClient(adminClient, "test", Constants.ACCOUNT_MANAGEMENT_CLIENT_ID)
.setClientId("account-changed")
.update()) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/IncludeOneTimeUseConditionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/IncludeOneTimeUseConditionTest.java
index 5c9ee3e..0562efe 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/IncludeOneTimeUseConditionTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/IncludeOneTimeUseConditionTest.java
@@ -59,12 +59,7 @@ public class IncludeOneTimeUseConditionTest extends AbstractSamlTest
private void testOneTimeUseConditionIncluded(Boolean oneTimeUseConditionShouldBeIncluded) throws IOException
{
- ClientsResource clients = adminClient.realm(REALM_NAME).clients();
- List<ClientRepresentation> foundClients = clients.findByClientId(SAML_CLIENT_ID_SALES_POST);
- assertThat(foundClients, hasSize(1));
- ClientResource clientRes = clients.get(foundClients.get(0).getId());
-
- try (Closeable c = new ClientAttributeUpdater(clientRes)
+ try (Closeable c = ClientAttributeUpdater.forClient(adminClient, REALM_NAME, SAML_CLIENT_ID_SALES_POST)
.setAttribute(SamlConfigAttributes.SAML_ONETIMEUSE_CONDITION, oneTimeUseConditionShouldBeIncluded.toString())
.update()) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/LogoutTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/LogoutTest.java
index 09fb266..69e4ecd 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/LogoutTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/saml/LogoutTest.java
@@ -16,7 +16,6 @@
*/
package org.keycloak.testsuite.saml;
-import org.keycloak.admin.client.resource.ClientsResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
@@ -361,10 +360,9 @@ public class LogoutTest extends AbstractSamlTest {
@Test
public void testLogoutPropagatesToSamlIdentityProvider() throws IOException {
final RealmResource realm = adminClient.realm(REALM_NAME);
- final ClientsResource clients = realm.clients();
try (
- Closeable sales = new ClientAttributeUpdater(clients.get(salesRep.getId()))
+ Closeable sales = ClientAttributeUpdater.forClient(adminClient, REALM_NAME, SAML_CLIENT_ID_SALES_POST)
.setFrontchannelLogout(true)
.removeAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE)
.setAttribute(SamlProtocol.SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE, "http://url")