How to configure storageProviderTimeout?

Hy everyone,

I’m new to KeyCloak and WildFly :slightly_smiling_face:

I have a User Storage SPI implementation which gets the users remotely and it’s working fine. However, when the connection is slow, a 3 seconds timeout exception occurs.

I believe the timeout is obtained in this code of AbstractStorageManager:

/**
 * 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;

protected Long getStorageProviderTimeout() {
    if (storageProviderTimeout == null) {
        storageProviderTimeout = Config.scope(configScope).getLong("storageProviderTimeout", STORAGE_PROVIDER_DEFAULT_TIMEOUT);
    }
    return storageProviderTimeout;
}

But I have no clue on how to configure the scope “user” with the property “storageProviderTimeout”.

How can this timeout be configured?

I’m using KeyCloak 13.0.0 and MacOS 11.3.1.

Thanks in advance,
Alex

I haven’t done this for a User Storage SPI implementation, but Config.Scope properties can be set up in your standalone.xml config.

The Config.Scope parameter is factory configuration that can be set up within standalone.xml , standalone-ha.xml , or domain.xml .

E.g.

<spi name="storage">
    <provider name="readonly-property-file" enabled="true">
        <properties>
            <property name="path" value="/other-users.properties"/>
        </properties>
    </provider>
</spi>

from (Server Developer Guide)

Thanks @xgp

This works for configuring properties of provider factories such as UserStorageProviderFactory. But, UserStoreManager (which extends AbstractStorageManager) is not a ProviderFactory and tries to get the property from the top level Config.

I think it would work if the XSD allowed something like the “theme” properties that are in standalone.xml (“staticMaxAge”, “cacheThemes”, etc.). It could be like this:

<user>
  <storageProviderTimeout>10000</storageProviderTimeout>
</user>

But the XSD doesn’t allow this.

1 Like

Just wondering if you ever found a solution? I too am in the same situation as you described in your original post.

Unfortunately, no. I couldn’t spend time on this issue and just moved on. However, this is something we will need to solve before going to production, so eventually we will have to revisit this issue. I’ll let you know if I find any solution or workaround.

1 Like

I am facing the same problem and could not find a solution.
We are implementing a UserStorageProvider where, under certain circumstances, processing takes longer than the preconfigured 3000 milliseconds. Has anyone here made any progress, otherwise I would raise an issue at keycloak.

No, still have not yet found a solution. I have posted this question on StackOverflow as well as the Keycloak User group and have yet to get any response. I see there is now an open issue in JIRA:
[KEYCLOAK-18856] Storage Provider Timeout is not configurable - Red Hat Issue Tracker
Hopefully this gets some attention. I just went and added my vote for the issue.

1 Like

Thanks for your vote! This is the issue I created yesterday.
The change was introduced almost 11 months ago in version 12.0.0. (KEYCLOAK-14973 Create GroupStorageManager · keycloak/keycloak@bdccfef · GitHub)
What makes me wonder is that this has not been noticed until now.

1 Like

Upvoted :+1: Thanks for opening the issue.

I think perhaps “wildfly-keycloak-server_1_1.xsd” and “KeycloakSubsystemParser.java” could be updated to handle those properties. But I’m new to KeyCloak, so better if a maintainer takes care of it.

Since the implementation of our UserStorageProvider may take longer than three seconds, I decided to take a really dark way to temporarily solve the problem.

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

:sweat_smile:
Use it with caution!

2 Likes

Nice workaround @deryoman. Thanks for sharing it :+1: