Disable Infinispan for map storage and avoid the component factory when creating a realm independent provider factory
Provide startup time in UserSessionProvider independent of Infinispan, cleanup code that is not necessary for the map storage as it isn't using Clustering. Move classes to the legacy module. Closes #12972
This commit is contained in:
parent
0eb10f2128
commit
cb81a17611
27 changed files with 133 additions and 113 deletions
|
@ -30,6 +30,7 @@ import org.jboss.logging.Logger;
|
|||
import org.keycloak.Config;
|
||||
import org.keycloak.cluster.ClusterProvider;
|
||||
import org.keycloak.cluster.ClusterProviderFactory;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.util.Retry;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory;
|
||||
|
@ -38,6 +39,7 @@ import org.keycloak.connections.infinispan.TopologyInfo;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.connections.infinispan.InfinispanUtil;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
|
@ -54,7 +56,7 @@ import java.util.stream.Collectors;
|
|||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class InfinispanClusterProviderFactory implements ClusterProviderFactory {
|
||||
public class InfinispanClusterProviderFactory implements ClusterProviderFactory, EnvironmentDependentProviderFactory {
|
||||
|
||||
public static final String PROVIDER_ID = "infinispan";
|
||||
|
||||
|
@ -190,6 +192,10 @@ public class InfinispanClusterProviderFactory implements ClusterProviderFactory
|
|||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return !Profile.isFeatureEnabled(Profile.Feature.MAP_STORAGE);
|
||||
}
|
||||
|
||||
@Listener
|
||||
public class ViewChangeListener {
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.keycloak.cluster.ClusterEvent;
|
|||
import org.keycloak.cluster.ClusterProvider;
|
||||
import org.keycloak.cluster.ManagedCacheManagerProvider;
|
||||
import org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.cache.infinispan.ClearCacheEvent;
|
||||
|
@ -45,6 +46,7 @@ import org.keycloak.models.cache.infinispan.events.RealmRemovedEvent;
|
|||
import org.keycloak.models.cache.infinispan.events.RealmUpdatedEvent;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.PostMigrationEvent;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.provider.InvalidationHandler.ObjectType;
|
||||
import org.keycloak.provider.ProviderEvent;
|
||||
|
||||
|
@ -62,7 +64,7 @@ import static org.keycloak.models.cache.infinispan.InfinispanCacheRealmProviderF
|
|||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class DefaultInfinispanConnectionProviderFactory implements InfinispanConnectionProviderFactory {
|
||||
public class DefaultInfinispanConnectionProviderFactory implements InfinispanConnectionProviderFactory, EnvironmentDependentProviderFactory {
|
||||
|
||||
protected static final Logger logger = Logger.getLogger(DefaultInfinispanConnectionProviderFactory.class);
|
||||
|
||||
|
@ -490,4 +492,9 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return !Profile.isFeatureEnabled(Profile.Feature.MAP_STORAGE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@ package org.keycloak.models.sessions.infinispan;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.provider.ProviderConfigurationBuilder;
|
||||
import org.keycloak.sessions.StickySessionEncoderProvider;
|
||||
|
@ -32,7 +34,7 @@ import java.util.List;
|
|||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class InfinispanStickySessionEncoderProviderFactory implements StickySessionEncoderProviderFactory {
|
||||
public class InfinispanStickySessionEncoderProviderFactory implements StickySessionEncoderProviderFactory, EnvironmentDependentProviderFactory {
|
||||
|
||||
private static final Logger log = Logger.getLogger(InfinispanStickySessionEncoderProviderFactory.class);
|
||||
|
||||
|
@ -87,4 +89,9 @@ public class InfinispanStickySessionEncoderProviderFactory implements StickySess
|
|||
.add()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return !Profile.isFeatureEnabled(Profile.Feature.MAP_STORAGE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -709,6 +709,12 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
|
|||
public void close() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartupTime(RealmModel realm) {
|
||||
// TODO: take realm.getNotBefore() into account?
|
||||
return session.getProvider(ClusterProvider.class).getClusterStartupTime();
|
||||
}
|
||||
|
||||
protected void removeUserSession(UserSessionEntity sessionEntity, boolean offline) {
|
||||
InfinispanChangelogBasedTransaction<String, UserSessionEntity> userSessionUpdateTx = getTransaction(offline);
|
||||
InfinispanChangelogBasedTransaction<UUID, AuthenticatedClientSessionEntity> clientSessionUpdateTx = getClientSessionTransaction(offline);
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.infinispan.persistence.remote.RemoteStore;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.cluster.ClusterProvider;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.util.Environment;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||
|
@ -58,6 +59,7 @@ import org.keycloak.models.sessions.infinispan.util.SessionTimeouts;
|
|||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.PostMigrationEvent;
|
||||
import org.keycloak.models.utils.ResetTimeOffsetEvent;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.provider.ProviderEvent;
|
||||
import org.keycloak.provider.ProviderEventListener;
|
||||
|
||||
|
@ -67,7 +69,7 @@ import java.util.UUID;
|
|||
import java.util.function.BiFunction;
|
||||
import static org.keycloak.models.sessions.infinispan.InfinispanAuthenticationSessionProviderFactory.PROVIDER_PRIORITY;
|
||||
|
||||
public class InfinispanUserSessionProviderFactory implements UserSessionProviderFactory {
|
||||
public class InfinispanUserSessionProviderFactory implements UserSessionProviderFactory, EnvironmentDependentProviderFactory {
|
||||
|
||||
private static final Logger log = Logger.getLogger(InfinispanUserSessionProviderFactory.class);
|
||||
|
||||
|
@ -350,5 +352,10 @@ public class InfinispanUserSessionProviderFactory implements UserSessionProvider
|
|||
public int order() {
|
||||
return PROVIDER_PRIORITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return !Profile.isFeatureEnabled(Profile.Feature.MAP_STORAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,3 +22,4 @@ org.keycloak.storage.client.ClientStorageProviderSpi
|
|||
org.keycloak.storage.group.GroupStorageProviderSpi
|
||||
org.keycloak.storage.clientscope.ClientScopeStorageProviderSpi
|
||||
org.keycloak.models.session.UserSessionPersisterSpi
|
||||
org.keycloak.cluster.ClusterSpi
|
||||
|
|
|
@ -54,8 +54,6 @@ public class MapRootAuthenticationSessionProvider implements AuthenticationSessi
|
|||
private final KeycloakSession session;
|
||||
protected final MapKeycloakTransaction<MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> tx;
|
||||
|
||||
private static final String AUTHENTICATION_SESSION_EVENTS = "AUTHENTICATION_SESSION_EVENTS";
|
||||
|
||||
public MapRootAuthenticationSessionProvider(KeycloakSession session, MapStorage<MapRootAuthenticationSessionEntity, RootAuthenticationSessionModel> sessionStore) {
|
||||
this.session = session;
|
||||
this.tx = sessionStore.createTransaction(session);
|
||||
|
@ -165,15 +163,6 @@ public class MapRootAuthenticationSessionProvider implements AuthenticationSessi
|
|||
return;
|
||||
}
|
||||
Objects.requireNonNull(authNotesFragment, "The provided authentication's notes map can't be null!");
|
||||
|
||||
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
|
||||
cluster.notify(
|
||||
AUTHENTICATION_SESSION_EVENTS,
|
||||
MapAuthenticationSessionAuthNoteUpdateEvent.create(compoundId.getRootSessionId(), compoundId.getTabId(),
|
||||
compoundId.getClientUUID(), authNotesFragment),
|
||||
true,
|
||||
ClusterProvider.DCNotify.ALL_BUT_LOCAL_DC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,8 +18,18 @@
|
|||
package org.keycloak.models.map.authorization;
|
||||
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.PermissionTicket;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.Resource;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.Scope;
|
||||
import org.keycloak.authorization.store.StoreFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.map.authorization.entity.MapPermissionTicketEntity;
|
||||
import org.keycloak.models.map.authorization.entity.MapPolicyEntity;
|
||||
import org.keycloak.models.map.authorization.entity.MapResourceEntity;
|
||||
import org.keycloak.models.map.authorization.entity.MapResourceServerEntity;
|
||||
import org.keycloak.models.map.authorization.entity.MapScopeEntity;
|
||||
import org.keycloak.models.map.storage.MapStorage;
|
||||
|
||||
|
||||
|
@ -35,8 +45,9 @@ public class MapAuthorizationStore implements StoreFactory {
|
|||
private final MapPermissionTicketStore permissionTicketStore;
|
||||
private boolean readOnly;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public MapAuthorizationStore(KeycloakSession session, MapStorage permissionTicketStore, MapStorage policyStore, MapStorage resourceServerStore, MapStorage resourceStore, MapStorage scopeStore, AuthorizationProvider provider) {
|
||||
public MapAuthorizationStore(KeycloakSession session, MapStorage<MapPermissionTicketEntity, PermissionTicket> permissionTicketStore,
|
||||
MapStorage<MapPolicyEntity, Policy> policyStore, MapStorage<MapResourceServerEntity, ResourceServer> resourceServerStore,
|
||||
MapStorage<MapResourceEntity, Resource> resourceStore, MapStorage<MapScopeEntity, Scope> scopeStore, AuthorizationProvider provider) {
|
||||
this.permissionTicketStore = new MapPermissionTicketStore(session, permissionTicketStore, provider);
|
||||
this.policyStore = new MapPolicyStore(session, policyStore, provider);
|
||||
this.resourceServerStore = new MapResourceServerStore(session, resourceServerStore, provider);
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package org.keycloak.models.map.authorization;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
import org.keycloak.authorization.model.PermissionTicket;
|
||||
|
@ -31,18 +30,20 @@ import org.keycloak.common.Profile;
|
|||
import org.keycloak.component.AmphibianProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.map.authorization.entity.MapPermissionTicketEntity;
|
||||
import org.keycloak.models.map.authorization.entity.MapPolicyEntity;
|
||||
import org.keycloak.models.map.authorization.entity.MapResourceEntity;
|
||||
import org.keycloak.models.map.authorization.entity.MapResourceServerEntity;
|
||||
import org.keycloak.models.map.authorization.entity.MapScopeEntity;
|
||||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||
import org.keycloak.models.map.storage.MapStorage;
|
||||
import org.keycloak.models.map.storage.MapStorageProvider;
|
||||
import org.keycloak.models.map.storage.MapStorageProviderFactory;
|
||||
import org.keycloak.models.map.storage.MapStorageSpi;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.provider.InvalidationHandler;
|
||||
|
||||
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.RESOURCE_SERVER_BEFORE_REMOVE;
|
||||
import static org.keycloak.models.map.common.AbstractMapProviderFactory.uniqueCounter;
|
||||
import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
|
@ -60,16 +61,14 @@ public class MapAuthorizationStoreFactory implements AmphibianProviderFactory<St
|
|||
|
||||
if (authzStore != null) return authzStore;
|
||||
|
||||
MapStorageProviderFactory storageProviderFactory = (MapStorageProviderFactory) getComponentFactory(session.getKeycloakSessionFactory(),
|
||||
MapStorageProvider.class, storageConfigScope, MapStorageSpi.NAME);
|
||||
final MapStorageProvider mapStorageProvider = storageProviderFactory.create(session);
|
||||
final MapStorageProvider mapStorageProvider = AbstractMapProviderFactory.getProviderFactoryOrComponentFactory(session, storageConfigScope).create(session);
|
||||
AuthorizationProvider provider = session.getProvider(AuthorizationProvider.class);
|
||||
|
||||
MapStorage permissionTicketStore = mapStorageProvider.getStorage(PermissionTicket.class);
|
||||
MapStorage policyStore = mapStorageProvider.getStorage(Policy.class);
|
||||
MapStorage resourceServerStore = mapStorageProvider.getStorage(ResourceServer.class);
|
||||
MapStorage resourceStore = mapStorageProvider.getStorage(Resource.class);
|
||||
MapStorage scopeStore = mapStorageProvider.getStorage(Scope.class);
|
||||
MapStorage<MapPermissionTicketEntity, PermissionTicket> permissionTicketStore = mapStorageProvider.getStorage(PermissionTicket.class);
|
||||
MapStorage<MapPolicyEntity, Policy> policyStore = mapStorageProvider.getStorage(Policy.class);
|
||||
MapStorage<MapResourceServerEntity, ResourceServer> resourceServerStore = mapStorageProvider.getStorage(ResourceServer.class);
|
||||
MapStorage<MapResourceEntity, Resource> resourceStore = mapStorageProvider.getStorage(Resource.class);
|
||||
MapStorage<MapScopeEntity, Scope> scopeStore = mapStorageProvider.getStorage(Scope.class);
|
||||
|
||||
authzStore = new MapAuthorizationStore(session,
|
||||
permissionTicketStore,
|
||||
|
|
|
@ -20,9 +20,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import org.keycloak.Config.Scope;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.map.storage.MapStorage;
|
||||
import org.keycloak.models.map.storage.MapStorageProvider;
|
||||
import org.keycloak.models.map.storage.MapStorageSpi;
|
||||
import org.keycloak.component.AmphibianProviderFactory;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
|
@ -31,8 +31,6 @@ import org.keycloak.provider.Provider;
|
|||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
|
@ -108,13 +106,34 @@ public abstract class AbstractMapProviderFactory<T extends Provider, V extends A
|
|||
}
|
||||
|
||||
protected MapStorage<V, M> getStorage(KeycloakSession session) {
|
||||
ProviderFactory<MapStorageProvider> storageProviderFactory = getComponentFactory(session.getKeycloakSessionFactory(),
|
||||
MapStorageProvider.class, storageConfigScope, MapStorageSpi.NAME);
|
||||
ProviderFactory<MapStorageProvider> storageProviderFactory = getProviderFactoryOrComponentFactory(session, storageConfigScope);
|
||||
final MapStorageProvider factory = storageProviderFactory.create(session);
|
||||
|
||||
return factory.getStorage(modelType);
|
||||
}
|
||||
|
||||
public static ProviderFactory<MapStorageProvider> getProviderFactoryOrComponentFactory(KeycloakSession session, Scope storageConfigScope) {
|
||||
ProviderFactory<MapStorageProvider> storageProviderFactory;
|
||||
if (!hasRealmSpecificStorage(session, storageConfigScope)) {
|
||||
String provider = storageConfigScope.get("provider");
|
||||
if (provider == null) {
|
||||
storageProviderFactory = session.getKeycloakSessionFactory().getProviderFactory(MapStorageProvider.class);
|
||||
} else {
|
||||
storageProviderFactory = session.getKeycloakSessionFactory().getProviderFactory(MapStorageProvider.class, provider);
|
||||
}
|
||||
} else {
|
||||
// If this is being implemented, make sure that the factory is being closed eventually.
|
||||
// When no cluster provider is available, the componentFactory will not be cached and a new instance is being returned all the time
|
||||
// when calling `getComponentFactory(session.getKeycloakSessionFactory(), MapStorageProvider.class, storageConfigScope, MapStorageSpi.NAME)`.
|
||||
throw new ModelException("not supported yet");
|
||||
}
|
||||
return storageProviderFactory;
|
||||
}
|
||||
|
||||
private static boolean hasRealmSpecificStorage(KeycloakSession session, Scope storageConfigScope) {
|
||||
// Once there is functionality for a realm-specific storage, implement the logic on how to detect it here.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
}
|
||||
|
|
|
@ -30,14 +30,11 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.models.map.common.AbstractMapProviderFactory;
|
||||
import org.keycloak.models.map.storage.MapStorage;
|
||||
import org.keycloak.models.map.storage.MapStorageProvider;
|
||||
import org.keycloak.models.map.storage.MapStorageProviderFactory;
|
||||
import org.keycloak.models.map.storage.MapStorageSpi;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.provider.InvalidationHandler;
|
||||
|
||||
import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProviderObjectType.REALM_BEFORE_REMOVE;
|
||||
import static org.keycloak.models.map.common.AbstractMapProviderFactory.uniqueCounter;
|
||||
import static org.keycloak.models.utils.KeycloakModelUtils.getComponentFactory;
|
||||
|
||||
public class MapEventStoreProviderFactory implements AmphibianProviderFactory<EventStoreProvider>, EnvironmentDependentProviderFactory, EventStoreProviderFactory, InvalidationHandler {
|
||||
|
||||
|
@ -62,15 +59,11 @@ public class MapEventStoreProviderFactory implements AmphibianProviderFactory<Ev
|
|||
MapEventStoreProvider provider = session.getAttribute(uniqueKey, MapEventStoreProvider.class);
|
||||
if (provider != null) return provider;
|
||||
|
||||
MapStorageProviderFactory storageProviderFactoryAe = (MapStorageProviderFactory) getComponentFactory(session.getKeycloakSessionFactory(),
|
||||
MapStorageProvider.class, storageConfigScopeAdminEvents, MapStorageSpi.NAME);
|
||||
final MapStorageProvider factoryAe = storageProviderFactoryAe.create(session);
|
||||
MapStorage adminEventsStore = factoryAe.getStorage(AdminEvent.class);
|
||||
final MapStorageProvider factoryAe = AbstractMapProviderFactory.getProviderFactoryOrComponentFactory(session, storageConfigScopeAdminEvents).create(session);
|
||||
MapStorage<MapAdminEventEntity, AdminEvent> adminEventsStore = factoryAe.getStorage(AdminEvent.class);
|
||||
|
||||
MapStorageProviderFactory storageProviderFactoryLe = (MapStorageProviderFactory) getComponentFactory(session.getKeycloakSessionFactory(),
|
||||
MapStorageProvider.class, storageConfigScopeLoginEvents, MapStorageSpi.NAME);
|
||||
final MapStorageProvider factoryLe = storageProviderFactoryLe.create(session);
|
||||
MapStorage loginEventsStore = factoryLe.getStorage(Event.class);
|
||||
final MapStorageProvider factoryLe = AbstractMapProviderFactory.getProviderFactoryOrComponentFactory(session, storageConfigScopeLoginEvents).create(session);
|
||||
MapStorage<MapAuthEventEntity, Event> loginEventsStore = factoryLe.getStorage(Event.class);
|
||||
|
||||
provider = new MapEventStoreProvider(session, loginEventsStore, adminEventsStore);
|
||||
session.setAttribute(uniqueKey, provider);
|
||||
|
|
|
@ -523,6 +523,11 @@ public class MapUserSessionProvider implements UserSessionProvider {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartupTime(RealmModel realm) {
|
||||
return realm.getNotBefore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all online and offline user sessions that belong to the provided {@link RealmModel}.
|
||||
* @param realm
|
||||
|
|
|
@ -218,24 +218,6 @@ public class StorageOptions {
|
|||
.buildTime(true)
|
||||
.build();
|
||||
|
||||
public static final Option<Boolean> STORAGE_CACHE_ENABLED = new OptionBuilder<>("cache-enabled", Boolean.class)
|
||||
.category(OptionCategory.STORAGE)
|
||||
.hidden()
|
||||
.buildTime(true)
|
||||
.build();
|
||||
|
||||
public static final Option<Boolean> STORAGE_CACHE_CLUSTER_ENABLED = new OptionBuilder<>("cache-cluster-enabled", Boolean.class)
|
||||
.category(OptionCategory.STORAGE)
|
||||
.hidden()
|
||||
.buildTime(true)
|
||||
.build();
|
||||
|
||||
public static final Option<String> STORAGE_CACHE_STICK_SESSION_ENABLED = new OptionBuilder<>("cache-stick-session-enabled", String.class)
|
||||
.category(OptionCategory.STORAGE)
|
||||
.hidden()
|
||||
.buildTime(true)
|
||||
.build();
|
||||
|
||||
public static final Option<String> STORAGE_CACHE_REALM_ENABLED = new OptionBuilder<>("cache-realm-enabled", String.class)
|
||||
.category(OptionCategory.STORAGE)
|
||||
.hidden()
|
||||
|
@ -290,12 +272,6 @@ public class StorageOptions {
|
|||
.buildTime(true)
|
||||
.build();
|
||||
|
||||
public static final Option<String> STORAGE_CACHE_COMPONENT_FACTORY = new OptionBuilder<>("cache-component-factory-cache", String.class)
|
||||
.category(OptionCategory.STORAGE)
|
||||
.hidden()
|
||||
.buildTime(true)
|
||||
.build();
|
||||
|
||||
public static final Option<String> STORAGE_LEGACY_SESSION_SUPPORT = new OptionBuilder<>("storage-legacy-session-support", String.class)
|
||||
.category(OptionCategory.STORAGE)
|
||||
.hidden()
|
||||
|
|
|
@ -229,12 +229,6 @@ final class StoragePropertyMappers {
|
|||
.transformer(StoragePropertyMappers::resolveMapStorageProvider)
|
||||
.paramLabel("type")
|
||||
.build(),
|
||||
fromOption(StorageOptions.STORAGE_CACHE_COMPONENT_FACTORY)
|
||||
.to("kc.spi-component-factory-default-caching-forced")
|
||||
.mapFrom("storage")
|
||||
.transformer(StoragePropertyMappers::isForceComponentFactoryCache)
|
||||
.paramLabel("type")
|
||||
.build(),
|
||||
fromOption(StorageOptions.STORAGE_PUBLIC_KEY_STORE)
|
||||
.to("kc.spi-public-key-storage-map-storage-provider")
|
||||
.mapFrom("storage")
|
||||
|
@ -247,24 +241,6 @@ final class StoragePropertyMappers {
|
|||
.transformer(StoragePropertyMappers::isLegacyStoreEnabled)
|
||||
.paramLabel(Boolean.TRUE + "|" + Boolean.FALSE)
|
||||
.build(),
|
||||
fromOption(StorageOptions.STORAGE_CACHE_ENABLED)
|
||||
.to("kc.spi-connections-infinispan-default-enabled")
|
||||
.mapFrom("storage")
|
||||
.transformer(StoragePropertyMappers::isLegacyStoreEnabled)
|
||||
.paramLabel(Boolean.TRUE + "|" + Boolean.FALSE)
|
||||
.build(),
|
||||
fromOption(StorageOptions.STORAGE_CACHE_CLUSTER_ENABLED)
|
||||
.to("kc.spi-cluster-infinispan-enabled")
|
||||
.mapFrom("storage")
|
||||
.transformer(StoragePropertyMappers::isLegacyStoreEnabled)
|
||||
.paramLabel(Boolean.TRUE + "|" + Boolean.FALSE)
|
||||
.build(),
|
||||
fromOption(StorageOptions.STORAGE_CACHE_STICK_SESSION_ENABLED)
|
||||
.to("kc.spi-sticky-session-encoder-infinispan-enabled")
|
||||
.mapFrom("storage")
|
||||
.transformer(StoragePropertyMappers::isLegacyStoreEnabled)
|
||||
.paramLabel(Boolean.TRUE + "|" + Boolean.FALSE)
|
||||
.build(),
|
||||
fromOption(StorageOptions.STORAGE_CACHE_CLEAR_REALM)
|
||||
.to("kc.spi-admin-realm-restapi-extension-clear-realm-cache-enabled")
|
||||
.mapFrom("storage")
|
||||
|
|
|
@ -27,7 +27,9 @@ import java.util.concurrent.Future;
|
|||
* Various utils related to clustering and concurrent tasks on cluster nodes
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
* @deprecated This is only available when the legacy store is enabled. Support for this will be eventually removed.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ClusterProvider extends Provider {
|
||||
|
||||
/**
|
||||
|
|
|
@ -61,7 +61,6 @@ org.keycloak.authentication.ClientAuthenticatorSpi
|
|||
org.keycloak.authentication.RequiredActionSpi
|
||||
org.keycloak.authentication.FormAuthenticatorSpi
|
||||
org.keycloak.authentication.FormActionSpi
|
||||
org.keycloak.cluster.ClusterSpi
|
||||
org.keycloak.authorization.policy.provider.PolicySpi
|
||||
org.keycloak.authorization.store.StoreFactorySpi
|
||||
org.keycloak.authorization.AuthorizationSpi
|
||||
|
|
|
@ -277,5 +277,5 @@ public interface UserSessionProvider extends Provider {
|
|||
|
||||
void close();
|
||||
|
||||
|
||||
int getStartupTime(RealmModel realm);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.keycloak.TokenVerifier;
|
|||
import org.keycloak.authentication.authenticators.util.AcrStore;
|
||||
import org.keycloak.broker.oidc.OIDCIdentityProvider;
|
||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||
import org.keycloak.cluster.ClusterProvider;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.VerificationException;
|
||||
|
@ -53,6 +52,7 @@ import org.keycloak.models.SingleUseObjectProvider;
|
|||
import org.keycloak.models.UserConsentModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.UserSessionProvider;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.RoleUtils;
|
||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||
|
@ -436,12 +436,12 @@ public class TokenManager {
|
|||
// Will throw OAuthErrorException if validation fails
|
||||
private void validateTokenReuse(KeycloakSession session, RealmModel realm, AccessToken refreshToken,
|
||||
AuthenticatedClientSessionModel clientSession, boolean refreshFlag) throws OAuthErrorException {
|
||||
int clusterStartupTime = session.getProvider(ClusterProvider.class).getClusterStartupTime();
|
||||
int startupTime = session.getProvider(UserSessionProvider.class).getStartupTime(realm);
|
||||
|
||||
if (clientSession.getCurrentRefreshToken() != null
|
||||
&& !refreshToken.getId().equals(clientSession.getCurrentRefreshToken())
|
||||
&& refreshToken.getIssuedAt() < clientSession.getTimestamp()
|
||||
&& clusterStartupTime <= clientSession.getTimestamp()) {
|
||||
&& startupTime <= clientSession.getTimestamp()) {
|
||||
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
|
||||
}
|
||||
|
||||
|
|
|
@ -44,15 +44,18 @@ public class InfinispanTestUtil {
|
|||
throw new IllegalStateException("Calling setTestingTimeService when testing TimeService was already set");
|
||||
}
|
||||
|
||||
logger.info("Will set KeycloakIspnTimeService to the infinispan cacheManager");
|
||||
|
||||
InfinispanConnectionProvider ispnProvider = session.getProvider(InfinispanConnectionProvider.class);
|
||||
if (ispnProvider != null) {
|
||||
logger.info("Will set KeycloakIspnTimeService to the infinispan cacheManager");
|
||||
EmbeddedCacheManager cacheManager = ispnProvider.getCache(InfinispanConnectionProvider.USER_SESSION_CACHE_NAME).getCacheManager();
|
||||
origTimeService = setTimeServiceToKeycloakTime(cacheManager);
|
||||
}
|
||||
}
|
||||
|
||||
public static void revertTimeService() {
|
||||
public static void revertTimeService(KeycloakSession session) {
|
||||
// Testing timeService not set. This shouldn't happen if this utility is properly used
|
||||
InfinispanConnectionProvider ispnProvider = session.getProvider(InfinispanConnectionProvider.class);
|
||||
if (ispnProvider != null) {
|
||||
if (origTimeService == null) {
|
||||
throw new IllegalStateException("Calling revertTimeService when testing TimeService was not set");
|
||||
}
|
||||
|
@ -61,3 +64,4 @@ public class InfinispanTestUtil {
|
|||
origTimeService = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,7 +201,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
|
|||
@Path("/revert-testing-infinispan-time-service")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response revertTestingInfinispanTimeService() {
|
||||
InfinispanTestUtil.revertTimeService();
|
||||
InfinispanTestUtil.revertTimeService(session);
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.keycloak.representations.idm.UserRepresentation;
|
|||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
|
@ -744,6 +745,11 @@ public class ResourceOwnerPasswordCredentialsGrantTest extends AbstractKeycloakT
|
|||
}
|
||||
|
||||
private int getAuthenticationSessionsCount() {
|
||||
if (ProfileAssume.isFeatureEnabled(Profile.Feature.MAP_STORAGE)) {
|
||||
// Currently, no access to the authentication sessions is available for map storage.
|
||||
// By return a constant, all tests in this test class can still pass.
|
||||
return 0;
|
||||
}
|
||||
return testingClient.testing().cache(InfinispanConnectionProvider.AUTHENTICATION_SESSIONS_CACHE_NAME).size();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@ package org.keycloak.testsuite.session;
|
|||
import org.infinispan.Cache;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.util.Retry;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||
|
@ -32,6 +34,7 @@ import org.keycloak.models.sessions.infinispan.changes.sessions.SessionData;
|
|||
import org.keycloak.models.sessions.infinispan.entities.UserSessionEntity;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AuthServerContainerExclude.AuthServer;
|
||||
import org.keycloak.testsuite.runonserver.RunOnServer;
|
||||
|
@ -52,6 +55,10 @@ public class LastSessionRefreshUnitTest extends AbstractKeycloakTest {
|
|||
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void checkNotMapStorage() {
|
||||
ProfileAssume.assumeFeatureDisabled(Profile.Feature.MAP_STORAGE);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupPeriodicTask() {
|
||||
|
|
|
@ -215,7 +215,7 @@ public class UserSessionProviderModelTest extends KeycloakModelTest {
|
|||
if (timer != null && timerTaskCtx != null) {
|
||||
timer.schedule(timerTaskCtx.getRunnable(), timerTaskCtx.getIntervalMillis(), PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME);
|
||||
|
||||
InfinispanTestUtil.revertTimeService();
|
||||
InfinispanTestUtil.revertTimeService(kcSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,7 +230,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
|
|||
timer.schedule(timerTaskCtx.getRunnable(), timerTaskCtx.getIntervalMillis(), PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME);
|
||||
}
|
||||
|
||||
InfinispanTestUtil.revertTimeService();
|
||||
InfinispanTestUtil.revertTimeService(kcSession);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,7 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
|
|||
timer.schedule(timerTaskCtx.getRunnable(), timerTaskCtx.getIntervalMillis(), PersisterLastSessionRefreshStoreFactory.DB_LSR_PERIODIC_TASK_NAME);
|
||||
}
|
||||
|
||||
InfinispanTestUtil.revertTimeService();
|
||||
InfinispanTestUtil.revertTimeService(kcSession);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue