Added LegacySessionSupport SPI
While some methods around onCache() are still called from the legacy code, all other methods log a warning with a stacktrace.
This commit is contained in:
parent
6f287e7ded
commit
14a369a8cc
12 changed files with 200 additions and 29 deletions
|
@ -23,6 +23,7 @@ import org.keycloak.credential.CredentialInput;
|
|||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.LegacySessionSupportProvider;
|
||||
import org.keycloak.models.cache.infinispan.events.InvalidationEvent;
|
||||
import org.keycloak.common.constants.ServiceAccountConstants;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
|
@ -372,7 +373,7 @@ public class UserCacheSession implements UserCache.Streams, OnCreateComponent, O
|
|||
|
||||
private void onCache(RealmModel realm, UserAdapter adapter, UserModel delegate) {
|
||||
((OnUserCache)getDelegate()).onCache(realm, adapter, delegate);
|
||||
((OnUserCache)session.userCredentialManager()).onCache(realm, adapter, delegate);
|
||||
((OnUserCache) session.getProvider(LegacySessionSupportProvider.class).userCredentialManager()).onCache(realm, adapter, delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.credential;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.common.util.reflections.Types;
|
||||
import org.keycloak.models.CredentialValidationOutput;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -33,8 +34,10 @@ import java.util.stream.Stream;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserCredentialStoreManager
|
||||
implements UserCredentialManager.Streams, OnUserCache {
|
||||
@Deprecated
|
||||
public class UserCredentialStoreManager implements UserCredentialManager.Streams, OnUserCache {
|
||||
|
||||
private final static Logger log = Logger.getLogger(UserCredentialStoreManager.class);
|
||||
|
||||
private final KeycloakSession session;
|
||||
|
||||
|
@ -45,90 +48,91 @@ public class UserCredentialStoreManager
|
|||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public void updateCredential(RealmModel realm, UserModel user, CredentialModel cred) {
|
||||
// TODO: no longer used in non-legacy code, can be removed
|
||||
warnAboutUsage();
|
||||
user.getUserCredentialManager().updateStoredCredential(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel cred) {
|
||||
// TODO: no longer used in non-legacy code, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().createStoredCredential(cred);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public boolean removeStoredCredential(RealmModel realm, UserModel user, String id) {
|
||||
// TODO: no longer used in non-legacy code, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().removeStoredCredentialById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public CredentialModel getStoredCredentialById(RealmModel realm, UserModel user, String id) {
|
||||
// TODO: no longer used in non-legacy code, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().getStoredCredentialById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public Stream<CredentialModel> getStoredCredentialsStream(RealmModel realm, UserModel user) {
|
||||
// TODO: no longer used in non-legacy code, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().getStoredCredentialsStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public Stream<CredentialModel> getStoredCredentialsByTypeStream(RealmModel realm, UserModel user, String type) {
|
||||
// TODO: no longer used in non-legacy code, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().getStoredCredentialsByTypeStream(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public CredentialModel getStoredCredentialByNameAndType(RealmModel realm, UserModel user, String name, String type) {
|
||||
// TODO: no longer used in non-legacy code, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().getStoredCredentialByNameAndType(name, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public boolean moveCredentialTo(RealmModel realm, UserModel user, String id, String newPreviousCredentialId){
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().moveStoredCredentialTo(id, newPreviousCredentialId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public boolean isValid(RealmModel realm, UserModel user, CredentialInput... inputs) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return isValid(realm, user, Arrays.asList(inputs));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public CredentialModel createCredentialThroughProvider(RealmModel realm, UserModel user, CredentialModel model){
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().createCredentialThroughProvider(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public void updateCredentialLabel(RealmModel realm, UserModel user, String credentialId, String userLabel){
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
user.getUserCredentialManager().updateCredentialLabel(credentialId, userLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public boolean isValid(RealmModel realm, UserModel user, List<CredentialInput> inputs) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().isValid(inputs);
|
||||
}
|
||||
|
||||
@Deprecated // Keep this up to and including Keycloak 19, then inline
|
||||
public static <T> Stream<T> getCredentialProviders(KeycloakSession session, Class<T> type) {
|
||||
// TODO: no longer used, can be removed
|
||||
// called via #onCache()
|
||||
// warnAboutUsage();
|
||||
return session.getKeycloakSessionFactory().getProviderFactoriesStream(CredentialProvider.class)
|
||||
.filter(f -> Types.supports(type, f, CredentialProviderFactory.class))
|
||||
.map(f -> (T) session.getProvider(CredentialProvider.class, f.getId()));
|
||||
|
@ -137,56 +141,57 @@ public class UserCredentialStoreManager
|
|||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().updateCredential(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
user.getUserCredentialManager().disableCredentialType(credentialType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public Stream<String> getDisableableCredentialTypesStream(RealmModel realm, UserModel user) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().getDisableableCredentialTypesStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public boolean isConfiguredFor(RealmModel realm, UserModel user, String type) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().isConfiguredFor(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public boolean isConfiguredLocally(RealmModel realm, UserModel user, String type) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().isConfiguredLocally(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public CredentialValidationOutput authenticate(KeycloakSession session, RealmModel realm, CredentialInput input) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return session.users().getUserByCredential(realm, input);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, then remove it together with the OnUserCache class
|
||||
public void onCache(RealmModel realm, CachedUserModel user, UserModel delegate) {
|
||||
// TODO: only called from legacy code (infinispan), can be removed
|
||||
// called by UserCacheSession#onCache, therefore don't warn here
|
||||
// warnAboutUsage();
|
||||
getCredentialProviders(session, OnUserCache.class).forEach(validator -> validator.onCache(realm, user, delegate));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated // Keep this up to and including Keycloak 19, the use methods on user.getUserCredentialManager() instead
|
||||
public Stream<String> getConfiguredUserStorageCredentialTypesStream(RealmModel realm, UserModel user) {
|
||||
// TODO: no longer used, can be removed
|
||||
warnAboutUsage();
|
||||
return user.getUserCredentialManager().getConfiguredUserStorageCredentialTypesStream();
|
||||
}
|
||||
|
||||
|
@ -195,4 +200,11 @@ public class UserCredentialStoreManager
|
|||
|
||||
}
|
||||
|
||||
private static void warnAboutUsage() {
|
||||
if (log.isEnabled(Logger.Level.WARN)) {
|
||||
// check if warning is enabled first before constructing the exception that is expensive to construct
|
||||
log.warn("Calls to session.userCredentialManager() now deprecated. Use user.getUserCredentialManager() instead!", new RuntimeException());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.keycloak.services.legacysessionsupport;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.LegacySessionSupportProvider;
|
||||
|
||||
/**
|
||||
* @author Alexander Schwartz
|
||||
*/
|
||||
public class LegacySessionSupportProviderFactoryImpl implements LegacySessionSupportProviderFactory<LegacySessionSupportProvider> {
|
||||
|
||||
private static final String PROVIDER_ID = "default";
|
||||
|
||||
@Override
|
||||
public LegacySessionSupportProvider create(KeycloakSession session) {
|
||||
return new LegacySessionSupportProviderImpl(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package org.keycloak.services.legacysessionsupport;
|
||||
|
||||
import org.keycloak.credential.UserCredentialStoreManager;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserCredentialManager;
|
||||
import org.keycloak.models.LegacySessionSupportProvider;
|
||||
|
||||
/**
|
||||
* @author Alexander Schwartz
|
||||
*/
|
||||
public class LegacySessionSupportProviderImpl implements LegacySessionSupportProvider {
|
||||
|
||||
private final KeycloakSession session;
|
||||
|
||||
public LegacySessionSupportProviderImpl(KeycloakSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public UserCredentialManager userCredentialManager() {
|
||||
// UserCacheSession calls session.userCredentialManager().onCache(), therefore can't trigger a warning here at the moment.
|
||||
return new UserCredentialStoreManager(session);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# Copyright 2022 Red Hat, Inc. and/or its affiliates
|
||||
# and other contributors as indicated by the @author tags.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
org.keycloak.services.legacysessionsupport.LegacySessionSupportProviderFactoryImpl
|
|
@ -0,0 +1,15 @@
|
|||
package org.keycloak.models;
|
||||
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
/**
|
||||
* Support for elements in Keycloak's session that are deprecated.
|
||||
* This allows the deprecated implementations to be moved to the legacy module.
|
||||
*
|
||||
* @author Alexander Schwartz
|
||||
*/
|
||||
public interface LegacySessionSupportProvider extends Provider {
|
||||
|
||||
@Deprecated
|
||||
UserCredentialManager userCredentialManager();
|
||||
}
|
|
@ -68,7 +68,9 @@ public interface SingleUserCredentialManager {
|
|||
@Deprecated
|
||||
boolean isConfiguredLocally(String type);
|
||||
|
||||
// TODO: not needed for new store? -> no, will be removed without replacement
|
||||
Stream<String> getConfiguredUserStorageCredentialTypesStream();
|
||||
|
||||
// TODO: not needed for new store? -> no, will be removed without replacement
|
||||
CredentialModel createCredentialThroughProvider(CredentialModel model);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.keycloak.services;
|
|||
|
||||
import org.keycloak.component.ComponentFactory;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.credential.UserCredentialStoreManager;
|
||||
import org.keycloak.jose.jws.DefaultTokenManager;
|
||||
import org.keycloak.keys.DefaultKeyManager;
|
||||
import org.keycloak.models.ClientProvider;
|
||||
|
@ -45,6 +44,7 @@ import org.keycloak.provider.ProviderFactory;
|
|||
import org.keycloak.provider.InvalidationHandler.InvalidableObjectType;
|
||||
import org.keycloak.provider.InvalidationHandler.ObjectType;
|
||||
import org.keycloak.services.clientpolicy.ClientPolicyManager;
|
||||
import org.keycloak.models.LegacySessionSupportProvider;
|
||||
import org.keycloak.sessions.AuthenticationSessionProvider;
|
||||
import org.keycloak.storage.DatastoreProvider;
|
||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||
|
@ -76,12 +76,13 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
private final Map<String, Object> attributes = new HashMap<>();
|
||||
private final Map<InvalidableObjectType, Set<Object>> invalidationMap = new HashMap<>();
|
||||
private DatastoreProvider datastoreProvider;
|
||||
private UserCredentialStoreManager userCredentialStorageManager;
|
||||
@Deprecated
|
||||
private UserCredentialManager userCredentialStorageManager;
|
||||
private UserSessionProvider sessionProvider;
|
||||
private UserLoginFailureProvider userLoginFailureProvider;
|
||||
private AuthenticationSessionProvider authenticationSessionProvider;
|
||||
private UserFederatedStorageProvider userFederatedStorageProvider;
|
||||
private KeycloakContext context;
|
||||
private final KeycloakContext context;
|
||||
private KeyManager keyManager;
|
||||
private ThemeManager themeManager;
|
||||
private TokenManager tokenManager;
|
||||
|
@ -229,8 +230,15 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public UserCredentialManager userCredentialManager() {
|
||||
if (userCredentialStorageManager == null) userCredentialStorageManager = new UserCredentialStoreManager(this);
|
||||
if (userCredentialStorageManager == null) {
|
||||
LegacySessionSupportProvider provider = this.getProvider(LegacySessionSupportProvider.class);
|
||||
if (provider == null) {
|
||||
throw new IllegalStateException("legacy support for a UserCredentialManager is not enabled");
|
||||
}
|
||||
userCredentialStorageManager = provider.userCredentialManager();
|
||||
}
|
||||
return userCredentialStorageManager;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package org.keycloak.services.legacysessionsupport;
|
||||
|
||||
import org.keycloak.models.LegacySessionSupportProvider;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
|
||||
/**
|
||||
* @author Alexander Schwartz
|
||||
*/
|
||||
public interface LegacySessionSupportProviderFactory<T extends LegacySessionSupportProvider> extends ProviderFactory<T> {
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package org.keycloak.services.legacysessionsupport;
|
||||
|
||||
import org.keycloak.models.LegacySessionSupportProvider;
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.Spi;
|
||||
|
||||
/**
|
||||
* @author Alexander Schwartz
|
||||
*/
|
||||
public class LegacySessionSupportSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public boolean isInternal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "legacy-session-support";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return LegacySessionSupportProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends LegacySessionSupportProviderFactory> getProviderFactoryClass() {
|
||||
return LegacySessionSupportProviderFactory.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,4 +28,4 @@ org.keycloak.protocol.oidc.grants.ciba.channel.AuthenticationChannelSpi
|
|||
org.keycloak.protocol.oidc.grants.ciba.resolvers.CIBALoginUserResolverSpi
|
||||
org.keycloak.protocol.oidc.rar.AuthorizationRequestParserSpi
|
||||
org.keycloak.services.resources.admin.ext.AdminRealmResourceSpi
|
||||
org.keycloak.credential.SingleUserCredentialManagerSpi
|
||||
org.keycloak.services.legacysessionsupport.LegacySessionSupportSpi
|
||||
|
|
|
@ -27,6 +27,8 @@ import org.keycloak.models.sessions.infinispan.InfinispanAuthenticationSessionPr
|
|||
import org.keycloak.models.sessions.infinispan.InfinispanSingleUseObjectProviderFactory;
|
||||
import org.keycloak.models.sessions.infinispan.InfinispanUserLoginFailureProviderFactory;
|
||||
import org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory;
|
||||
import org.keycloak.services.legacysessionsupport.LegacySessionSupportProviderFactory;
|
||||
import org.keycloak.services.legacysessionsupport.LegacySessionSupportSpi;
|
||||
import org.keycloak.sessions.AuthenticationSessionSpi;
|
||||
import org.keycloak.sessions.StickySessionEncoderProviderFactory;
|
||||
import org.keycloak.sessions.StickySessionEncoderSpi;
|
||||
|
@ -62,6 +64,8 @@ public class Infinispan extends KeycloakModelParameters {
|
|||
.add(ActionTokenStoreSpi.class)
|
||||
.add(SingleUseObjectSpi.class)
|
||||
|
||||
.add(LegacySessionSupportSpi.class) // necessary as it will call session.userCredentialManager().onCache()
|
||||
|
||||
.build();
|
||||
|
||||
static final Set<Class<? extends ProviderFactory>> ALLOWED_FACTORIES = ImmutableSet.<Class<? extends ProviderFactory>>builder()
|
||||
|
@ -76,6 +80,7 @@ public class Infinispan extends KeycloakModelParameters {
|
|||
.add(InfinispanSingleUseObjectProviderFactory.class)
|
||||
.add(StickySessionEncoderProviderFactory.class)
|
||||
.add(TimerProviderFactory.class)
|
||||
.add(LegacySessionSupportProviderFactory.class)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue