fix: streamlining the client scope update (#40808)

closes: #40805

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Steven Hawkins
2025-07-07 11:57:39 -04:00
committed by GitHub
parent 0077b27c1f
commit d74e71e5ed
@@ -18,9 +18,11 @@
package org.keycloak.models.utils;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
@@ -635,25 +637,28 @@ public class RepresentationToModel {
public static void updateClientScopes(ClientRepresentation resourceRep, ClientModel client) {
if (resourceRep.getDefaultClientScopes() != null || resourceRep.getOptionalClientScopes() != null) {
// First remove all default/built in client scopes
for (ClientScopeModel clientScope : client.getClientScopes(true).values()) {
client.removeClientScope(clientScope);
// first collect all the desired scopes
LinkedHashMap<String, Boolean> allScopes = new LinkedHashMap<String, Boolean>();
Optional.ofNullable(resourceRep.getOptionalClientScopes()).ifPresent(scopes -> scopes.forEach(scope -> allScopes.put(scope, false)));
Optional.ofNullable(resourceRep.getDefaultClientScopes()).ifPresent(scopes -> scopes.forEach(scope -> allScopes.put(scope, true)));
// next determine what already exists
Map<Map.Entry<String, Boolean>, ClientScopeModel> existing = new HashMap<Map.Entry<String,Boolean>, ClientScopeModel>();
client.getClientScopes(false).entrySet().stream().forEach(entry -> existing.put(new AbstractMap.SimpleEntry<String, Boolean>(entry.getKey(), false), entry.getValue()));
client.getClientScopes(true).entrySet().stream().forEach(entry -> existing.put(new AbstractMap.SimpleEntry<String, Boolean>(entry.getKey(), true), entry.getValue()));
// remove anything that isn't desired - this includes client scopes that are toggling the default flag
for (Entry<Entry<String, Boolean>, ClientScopeModel> entry : existing.entrySet()) {
if (Optional.ofNullable(allScopes.get(entry.getKey().getKey())).filter(entry.getKey().getValue()::equals).isEmpty()) {
client.removeClientScope(entry.getValue());
}
}
// First remove all default/built in client scopes
for (ClientScopeModel clientScope : client.getClientScopes(false).values()) {
client.removeClientScope(clientScope);
}
}
if (resourceRep.getDefaultClientScopes() != null) {
for (String clientScopeName : resourceRep.getDefaultClientScopes()) {
addClientScopeToClient(client.getRealm(), client, clientScopeName, true);
}
}
if (resourceRep.getOptionalClientScopes() != null) {
for (String clientScopeName : resourceRep.getOptionalClientScopes()) {
addClientScopeToClient(client.getRealm(), client, clientScopeName, false);
// finally add in all the desired
for (Map.Entry<String, Boolean> entry : allScopes.entrySet()) {
if (!existing.containsKey(entry)) {
addClientScopeToClient(client.getRealm(), client, entry.getKey(), entry.getValue());
}
}
}
}