I have developed an implementation of the User Storage SPI that calls an API in a legacy system to migrate users. I need to configure my own value for storageProviderTimeout
as there is a remote chance that it will take longer than the default 3 seconds to get a response. I have already configured the socket-timeout-millis
to be more than the default 5 seconds before timing out, but this does not help as the storageProviderTimeout
has a default of 3 seconds. Upon looking at the Keycloak source code, specifically AbstractStorageManager.java
there is a mention of this value being configurable:
/** * Timeouts are used as time boundary for obtaining models from an external storage. Default value is set * to 3000 milliseconds and it's configurable. */ private static final Long STORAGE_PROVIDER_DEFAULT_TIMEOUT = 3000L;
The function to read the configured value looks like this:
protected Long getStorageProviderTimeout() { if (storageProviderTimeout == null) { storageProviderTimeout = Config.scope(configScope).getLong("storageProviderTimeout", STORAGE_PROVIDER_DEFAULT_TIMEOUT); } return storageProviderTimeout; }
When the UserStorageManager
instance is created (which extends AbstractUserManager
the constructor instantiates the superclass with this code:
public UserStorageManager(KeycloakSession session) { super(session, UserStorageProviderFactory.class, UserStorageProvider.class, UserStorageProviderModel::new, "user"); }
where "user"
is what later gets passed to Config.scope()
in the getStorageProviderTimeout()
function.
What I’ve tried so far is manually adding the tag <user>
in standalone-ha.xml
at the same level as the <theme>
tag, like this:
<user> <storageProviderTimeout>10000</storageProviderTimeout> </user>
but upon booting Keycloak, I get this error:
10:55:59,730 ERROR [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0055: Caught exception during boot: org.jboss.as.controller.persistence.ConfigurationPersistenceException: WFLYCTL0085: Failed to parse configuration at org.jboss.as.controller@15.0.1.Final//org.jboss.as.controller.persistence.XmlConfigurationPersister.load(XmlConfigurationPersister.java:143) at org.jboss.as.server@15.0.1.Final//org.jboss.as.server.ServerService.boot(ServerService.java:403) at org.jboss.as.controller@15.0.1.Final//org.jboss.as.controller.AbstractControllerService$1.run(AbstractControllerService.java:416) at java.base/java.lang.Thread.run(Thread.java:834) Caused by: javax.xml.stream.XMLStreamException: Unknown keycloak-server subsystem tag: user
I hope someone can shed some light on this for me as it feels like I’m missing something obvious. Thanks in advance!
Advertisement
Answer
As discussed here https://keycloak.discourse.group/t/how-to-configure-storageprovidertimeout/9171, there are currently no possibilties to configure this property.
There is an open issue to address this problem: https://issues.redhat.com/browse/KEYCLOAK-18856
As a temporarily quick and dirty workaround you can set the value at runtime via reflections in e.g. your custom UserStorageProvier implementation:
public class CustomUserStorageProviderFactory implements UserStorageProviderFactory<CustomUserStorageProvider> { @Override public void onCreate(KeycloakSession session, RealmModel realm, ComponentModel model) { UserProvider userProvider = session.userStorageManager(); try { Field field = userProvider.getClass().getSuperclass().getDeclaredField("STORAGE_PROVIDER_DEFAULT_TIMEOUT"); field.setAccessible(true); Field modifiers = field.getClass().getDeclaredField("modifiers"); modifiers.setAccessible(true); modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(userProvider, 5000L); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); } }
}