Skip to content
Advertisement

Is there a way to configure the storageProviderTimeout in Keycloak?

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);
    }
}

}

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement