From 95614e8b4022306ffac328b85130403cc157fb18 Mon Sep 17 00:00:00 2001 From: Hynek Mlnarik Date: Mon, 6 Dec 2021 15:55:45 +0100 Subject: [PATCH] Fix NPE for component creation when realm unset but config known Fixes #9019 --- .../keycloak/models/utils/KeycloakModelUtils.java | 14 ++++++++++---- .../DefaultComponentFactoryProviderFactory.java | 7 ++++++- .../keycloak/services/DefaultKeycloakSession.java | 5 +---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java index 482500ca23..a867f5e346 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java @@ -306,7 +306,7 @@ public final class KeycloakModelUtils { String componentId = config.get("componentId"); if (realmId == null || componentId == null) { realmId = "ROOT"; - ComponentModel cm = new ScopeComponentModel(providerClass, config, spiName); + ComponentModel cm = new ScopeComponentModel(providerClass, config, spiName, realmId); return factory.getProviderFactory(providerClass, realmId, cm.getId(), k -> cm); } else { return factory.getProviderFactory(providerClass, realmId, componentId, componentModelGetter(realmId, componentId)); @@ -318,14 +318,16 @@ public final class KeycloakModelUtils { private final String componentId; private final String providerId; private final String providerType; + private final String realmId; private final Scope config; - public ScopeComponentModel(Class providerClass, Scope baseConfiguration, String spiName) { + public ScopeComponentModel(Class providerClass, Scope baseConfiguration, String spiName, String realmId) { final String pr = baseConfiguration.get("provider", Config.getProvider(spiName)); this.providerId = pr == null ? "default" : pr; this.config = baseConfiguration.scope(this.providerId); - this.componentId = spiName + "-" + this.providerId; + this.componentId = spiName + "- " + (realmId == null ? "" : "f:" + realmId + ":") + this.providerId; + this.realmId = realmId; this.providerType = providerClass.getName(); } @@ -349,6 +351,11 @@ public final class KeycloakModelUtils { return componentId; } + @Override + public String getParentId() { + return realmId; + } + @Override public boolean get(String key, boolean defaultValue) { return config.getBoolean(key, defaultValue); @@ -366,7 +373,6 @@ public final class KeycloakModelUtils { @Override public String get(String key, String defaultValue) { - return config.get(key, defaultValue); } diff --git a/services/src/main/java/org/keycloak/services/DefaultComponentFactoryProviderFactory.java b/services/src/main/java/org/keycloak/services/DefaultComponentFactoryProviderFactory.java index 8f20c46a47..e2d34f8e28 100644 --- a/services/src/main/java/org/keycloak/services/DefaultComponentFactoryProviderFactory.java +++ b/services/src/main/java/org/keycloak/services/DefaultComponentFactoryProviderFactory.java @@ -143,7 +143,12 @@ public class DefaultComponentFactoryProviderFactory implements ComponentFactoryP newFactory.init(configScope); newFactory.postInit(factory); - dependentInvalidations.computeIfAbsent(realmId, k -> ConcurrentHashMap.newKeySet()).add(componentId); + if (realmId == null) { + realmId = configScope.getComponentParentId(); + } + if (realmId != null) { + dependentInvalidations.computeIfAbsent(realmId, k -> ConcurrentHashMap.newKeySet()).add(componentId); + } dependentInvalidations.computeIfAbsent(newFactory.getClass(), k -> ConcurrentHashMap.newKeySet()).add(componentId); return newFactory; diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java index f95f75f572..69e71e4e9f 100644 --- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java +++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java @@ -354,15 +354,12 @@ public class DefaultKeycloakSession implements KeycloakSession { Integer hash = clazz.hashCode() + componentId.hashCode(); T provider = (T) providers.get(hash); final RealmModel realm = getContext().getRealm(); - if (realm == null) { - throw new IllegalArgumentException("Realm not set in the context."); - } // KEYCLOAK-11890 - Avoid using HashMap.computeIfAbsent() to implement logic in outer if() block below, // since per JDK-8071667 the remapping function should not modify the map during computation. While // allowed on JDK 1.8, attempt of such a modification throws ConcurrentModificationException with JDK 9+ if (provider == null) { - final String realmId = realm.getId(); + final String realmId = realm == null ? null : realm.getId(); ProviderFactory providerFactory = factory.getProviderFactory(clazz, realmId, componentId, modelGetter); if (providerFactory != null) { provider = providerFactory.create(this);