Hi all,
I’m working on a problem I can’t figure out, where the first load of a UserStorageProvider
fails, but subsequent load succeeds. In some cases, the provider should be loaded by an attempt to load a user (e.g. during a login attempt), and in others, it’s from a ImportSynchronization
implementation in the sync()
method. In all cases, it worked in versions of Keycloak before 19.
In the case of the ImportSynchronization
implementation, I did some debugging of how I load the provider to see what’s going on:
public static MyUserStorageProvider getMyProvider(KeycloakSession session, ComponentModel fedModel) {
log.infof("getProvider for %s, id=%s, providerId=%s", fedModel, fedModel.getId(), fedModel.getProviderId());
MyUserStorageProvider provider = session.getProvider(MyUserStorageProvider.class, fedModel);
log.infof("got MyUserStorageProvider %s with ComponentModel %s", provider, fedModel);
if (provider == null) {
Provider p = getMyProvider(session);
if (p != null) {
provider = (MyUserStorageProvider)p;
log.infof("got MyUserStorageProvider %s via set of UserStorageProvders", provider, fedModel);
}
}
return provider;
}
public static UserStorageProvider getMyProvider(KeycloakSession session) {
Set<UserStorageProvider> userStorageProviders = session.getAllProviders(UserStorageProvider.class);
log.infof("Found %d providers for type UserStorageProvider", userStorageProviders.size());
return userStorageProviders.stream()
.filter(pr -> {
log.infof("UserStorageProvider is %s", pr);
if (pr == null) return false;
log.infof("found UserStorageProvider of type %s", pr.getClass().getName());
return (pr instanceof MyUserStorageProvider);
})
.findAny()
.orElse(null);
}
The resulting output on the first call is:
2023-01-07 13:30:52 12:30:52,620 INFO [test.LegacyStorageUtils] (Timer-2) getProvider for org.keycloak.storage.UserStorageProviderModel@2949d279, id=660ab6d8-c0eb-45e0-a35e-039d049c5451, providerId=my
2023-01-07 13:30:52 12:30:52,622 INFO [test.LegacyStorageUtils] (Timer-2) got MyUserStorageProvider null with ComponentModel org.keycloak.storage.UserStorageProviderModel@2949d279
2023-01-07 13:30:52 12:30:52,622 INFO [test.LegacyStorageUtils] (Timer-2) Found 1 providers for type UserStorageProvider
2023-01-07 13:30:52 12:30:52,623 INFO [test.LegacyStorageUtils] (Timer-2) UserStorageProvider is null
The method session.getProvider(MyUserStorageProvider.class, fedModel);
used to work as expected, but now returns null. Furthermore, the use of session.getAllProviders(UserStorageProvider.class)
returns a Set with a single, null entry. I know that there has been a lot of work on these classes, and there have been deprecations in how we’re supposed to look up providers, but I’ve tried all of the new getComponentProvider
methods, and I always get null the first time they are called.
Any ideas as to why this is happening, but only on the first call? Is there some, new, lazy-loading logic to be aware of? Is there a feasible workaround that anyone has used?
Thank you!