From 2b51d6f4ac9f4f5f71da6e8453fbac217e4f725c Mon Sep 17 00:00:00 2001 From: Alexander Schwartz Date: Tue, 28 Oct 2025 17:10:24 +0100 Subject: [PATCH] Avoid holding on to the realm in cached configurations Closes #43744 Signed-off-by: Alexander Schwartz --- .../models/cache/infinispan/RealmAdapter.java | 4 +-- .../infinispan/entities/CachedRealm.java | 12 +++----- .../org/keycloak/models/AbstractConfig.java | 1 + .../java/org/keycloak/models/CibaConfig.java | 30 ++++++++----------- .../java/org/keycloak/models/ParConfig.java | 12 ++------ 5 files changed, 22 insertions(+), 37 deletions(-) diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java index 4da6a0ac43b..c08f009d7d1 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java @@ -727,13 +727,13 @@ public class RealmAdapter implements CachedRealmModel { @Override public CibaConfig getCibaPolicy() { if (isUpdated()) return updated.getCibaPolicy(); - return cached.getCibaConfig(session, modelSupplier); + return cached.getCibaConfig(modelSupplier); } @Override public ParConfig getParPolicy() { if (isUpdated()) return updated.getParPolicy(); - return cached.getParConfig(session, modelSupplier); + return cached.getParConfig(modelSupplier); } @Override diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java index 57a680a7e49..8febcbb7887 100755 --- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java +++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java @@ -112,8 +112,6 @@ public class CachedRealm extends AbstractExtendableRevisioned { protected int accessCodeLifespanUserAction; protected int accessCodeLifespanLogin; protected LazyLoader deviceConfig; - protected LazyLoader cibaConfig; - protected LazyLoader parConfig; protected int actionTokenGeneratedByAdminLifespan; protected int actionTokenGeneratedByUserLifespan; protected int notBefore; @@ -229,8 +227,6 @@ public class CachedRealm extends AbstractExtendableRevisioned { accessTokenLifespanForImplicitFlow = model.getAccessTokenLifespanForImplicitFlow(); accessCodeLifespan = model.getAccessCodeLifespan(); deviceConfig = new DefaultLazyLoader<>(OAuth2DeviceConfig::new, null); - cibaConfig = new DefaultLazyLoader<>(CibaConfig::new, null); - parConfig = new DefaultLazyLoader<>(ParConfig::new, null); accessCodeLifespanUserAction = model.getAccessCodeLifespanUserAction(); accessCodeLifespanLogin = model.getAccessCodeLifespanLogin(); actionTokenGeneratedByAdminLifespan = model.getActionTokenGeneratedByAdminLifespan(); @@ -531,12 +527,12 @@ public class CachedRealm extends AbstractExtendableRevisioned { return deviceConfig.get(session, modelSupplier); } - public CibaConfig getCibaConfig(KeycloakSession session, Supplier modelSupplier) { - return cibaConfig.get(session, modelSupplier); + public CibaConfig getCibaConfig(Supplier modelSupplier) { + return new CibaConfig(modelSupplier.get()); } - public ParConfig getParConfig(KeycloakSession session, Supplier modelSupplier) { - return parConfig.get(session, modelSupplier); + public ParConfig getParConfig(Supplier modelSupplier) { + return new ParConfig(modelSupplier.get()); } public int getActionTokenGeneratedByAdminLifespan() { diff --git a/server-spi/src/main/java/org/keycloak/models/AbstractConfig.java b/server-spi/src/main/java/org/keycloak/models/AbstractConfig.java index b0c03e473bf..503500e50e1 100644 --- a/server-spi/src/main/java/org/keycloak/models/AbstractConfig.java +++ b/server-spi/src/main/java/org/keycloak/models/AbstractConfig.java @@ -21,6 +21,7 @@ import java.util.function.Supplier; public abstract class AbstractConfig implements Serializable { + @Deprecated(since = "26.5", forRemoval = true) protected transient Supplier realm; // Make sure setters are not called when calling this from constructor to avoid DB updates diff --git a/server-spi/src/main/java/org/keycloak/models/CibaConfig.java b/server-spi/src/main/java/org/keycloak/models/CibaConfig.java index 266c98ca80e..c0ca00bcbf3 100644 --- a/server-spi/src/main/java/org/keycloak/models/CibaConfig.java +++ b/server-spi/src/main/java/org/keycloak/models/CibaConfig.java @@ -42,10 +42,10 @@ public class CibaConfig extends AbstractConfig { public static final int DEFAULT_CIBA_POLICY_INTERVAL = 5; public static final String DEFAULT_CIBA_POLICY_AUTH_REQUESTED_USER_HINT = "login_hint"; - private String backchannelTokenDeliveryMode = DEFAULT_CIBA_POLICY_TOKEN_DELIVERY_MODE; - private int expiresIn = DEFAULT_CIBA_POLICY_EXPIRES_IN; - private int poolingInterval = DEFAULT_CIBA_POLICY_INTERVAL; - private String authRequestedUserHint = DEFAULT_CIBA_POLICY_AUTH_REQUESTED_USER_HINT; + private String backchannelTokenDeliveryMode; + private int expiresIn; + private int poolingInterval; + private String authRequestedUserHint; // client attribute names public static final String OIDC_CIBA_GRANT_ENABLED = "oidc.ciba.grant.enabled"; @@ -54,24 +54,20 @@ public class CibaConfig extends AbstractConfig { public static final String CIBA_BACKCHANNEL_AUTH_REQUEST_SIGNING_ALG = "ciba.backchannel.auth.request.signing.alg"; public CibaConfig(RealmModel realm) { - this.realm = () -> realm; - - setBackchannelTokenDeliveryMode(realm.getAttribute(CIBA_BACKCHANNEL_TOKEN_DELIVERY_MODE)); - - String expiresIn = realm.getAttribute(CIBA_EXPIRES_IN); - - if (StringUtil.isNotBlank(expiresIn)) { - setExpiresIn(Integer.parseInt(expiresIn)); + this.backchannelTokenDeliveryMode = realm.getAttribute(CIBA_BACKCHANNEL_TOKEN_DELIVERY_MODE); + if (this.backchannelTokenDeliveryMode == null) { + this.backchannelTokenDeliveryMode = DEFAULT_CIBA_POLICY_TOKEN_DELIVERY_MODE; } - String interval = realm.getAttribute(CIBA_INTERVAL); + this.expiresIn = realm.getAttribute(CIBA_EXPIRES_IN, DEFAULT_CIBA_POLICY_EXPIRES_IN); - if (StringUtil.isNotBlank(interval)) { - setPoolingInterval(Integer.parseInt(interval)); + this.poolingInterval = realm.getAttribute(CIBA_INTERVAL, DEFAULT_CIBA_POLICY_INTERVAL); + + this.authRequestedUserHint = realm.getAttribute(CIBA_AUTH_REQUESTED_USER_HINT); + if (authRequestedUserHint == null) { + authRequestedUserHint = DEFAULT_CIBA_POLICY_AUTH_REQUESTED_USER_HINT; } - setAuthRequestedUserHint(realm.getAttribute(CIBA_AUTH_REQUESTED_USER_HINT)); - this.realmForWrite = () -> realm; } diff --git a/server-spi/src/main/java/org/keycloak/models/ParConfig.java b/server-spi/src/main/java/org/keycloak/models/ParConfig.java index 0144b9eb1c4..d49a4f4386a 100644 --- a/server-spi/src/main/java/org/keycloak/models/ParConfig.java +++ b/server-spi/src/main/java/org/keycloak/models/ParConfig.java @@ -16,8 +16,6 @@ */ package org.keycloak.models; -import org.keycloak.utils.StringUtil; - public class ParConfig extends AbstractConfig { // realm attribute names @@ -26,19 +24,13 @@ public class ParConfig extends AbstractConfig { // default value public static final int DEFAULT_PAR_REQUEST_URI_LIFESPAN = 60; // sec - private int requestUriLifespan = DEFAULT_PAR_REQUEST_URI_LIFESPAN; + private int requestUriLifespan; // client attribute names public static final String REQUIRE_PUSHED_AUTHORIZATION_REQUESTS = "require.pushed.authorization.requests"; public ParConfig(RealmModel realm) { - this.realm = () -> realm; - - String requestUriLifespan = realm.getAttribute(PAR_REQUEST_URI_LIFESPAN); - - if (StringUtil.isNotBlank(requestUriLifespan)) { - setRequestUriLifespan(Integer.parseInt(requestUriLifespan)); - } + this.requestUriLifespan = realm.getAttribute(PAR_REQUEST_URI_LIFESPAN, DEFAULT_PAR_REQUEST_URI_LIFESPAN); this.realmForWrite = () -> realm; }