parent
637c47ac0e
commit
2a5b5c4a40
2 changed files with 53 additions and 5 deletions
|
@ -37,7 +37,6 @@ import org.keycloak.storage.SearchableModelField;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -66,7 +65,6 @@ public class HotRodUserSessionTransaction<K> extends ConcurrentHashMapKeycloakTr
|
|||
}
|
||||
|
||||
private MapAuthenticatedClientSessionEntity wrapClientSessionEntityToClientSessionAwareDelegate(MapAuthenticatedClientSessionEntity d) {
|
||||
if (!clientSessionTransaction.exists(d.getId())) return null;
|
||||
return new MapAuthenticatedClientSessionEntityDelegate(new HotRodAuthenticatedClientSessionEntityDelegateProvider(d) {
|
||||
@Override
|
||||
public MapAuthenticatedClientSessionEntity loadClientSessionFromDatabase() {
|
||||
|
@ -79,20 +77,33 @@ public class HotRodUserSessionTransaction<K> extends ConcurrentHashMapKeycloakTr
|
|||
if (entity == null) return null;
|
||||
|
||||
return new MapUserSessionEntityDelegate(new SimpleDelegateProvider<>(entity)) {
|
||||
|
||||
private boolean filterAndRemoveNotExpired(MapAuthenticatedClientSessionEntity clientSession) {
|
||||
if (!clientSessionTransaction.exists(clientSession.getId())) {
|
||||
// If client session does not exist, remove the reference to it from userSessionEntity loaded in this transaction
|
||||
entity.removeAuthenticatedClientSession(clientSession.getClientId());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<MapAuthenticatedClientSessionEntity> getAuthenticatedClientSessions() {
|
||||
Set<MapAuthenticatedClientSessionEntity> clientSessions = super.getAuthenticatedClientSessions();
|
||||
return clientSessions == null ? null : clientSessions.stream()
|
||||
// Find whether client session still exists in Infinispan and if not, remove the reference from user session
|
||||
.filter(this::filterAndRemoveNotExpired)
|
||||
.map(HotRodUserSessionTransaction.this::wrapClientSessionEntityToClientSessionAwareDelegate)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MapAuthenticatedClientSessionEntity> getAuthenticatedClientSession(String clientUUID) {
|
||||
return super.getAuthenticatedClientSession(clientUUID)
|
||||
.map(HotRodUserSessionTransaction.this::wrapClientSessionEntityToClientSessionAwareDelegate)
|
||||
.filter(Objects::nonNull);
|
||||
// Find whether client session still exists in Infinispan and if not, remove the reference from user sessionZ
|
||||
.filter(this::filterAndRemoveNotExpired)
|
||||
.map(HotRodUserSessionTransaction.this::wrapClientSessionEntityToClientSessionAwareDelegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,6 +40,10 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hamcrest.Matchers.aMapWithSize;
|
||||
import static org.hamcrest.Matchers.anEmptyMap;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.keycloak.protocol.oidc.OIDCConfigAttributes.CLIENT_SESSION_IDLE_TIMEOUT;
|
||||
import static org.keycloak.protocol.oidc.OIDCConfigAttributes.CLIENT_SESSION_MAX_LIFESPAN;
|
||||
|
||||
@RequireProvider(UserSessionProvider.class)
|
||||
@RequireProvider(value = HotRodConnectionProvider.class, only = DefaultHotRodConnectionProviderFactory.PROVIDER_ID)
|
||||
|
@ -114,6 +118,39 @@ public class HotRodUserSessionClientSessionRelationshipTest extends KeycloakMode
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpiredClientSessionReferenceIsNotPresentInUserSession() {
|
||||
// Set lower client session timeouts
|
||||
withRealm(realmId, (session, realm) -> {
|
||||
ClientModel client = realm.getClientByClientId(CLIENT0_CLIENT_ID);
|
||||
client.setAttribute(CLIENT_SESSION_IDLE_TIMEOUT, "60");
|
||||
client.setAttribute(CLIENT_SESSION_MAX_LIFESPAN, "65");
|
||||
return null;
|
||||
});
|
||||
|
||||
AtomicReference<String> uSessionId = new AtomicReference<>();
|
||||
AtomicReference<String> cSessionId = new AtomicReference<>();
|
||||
prepareSessions(uSessionId, cSessionId);
|
||||
|
||||
// Move in time when client session should be expired but user session not
|
||||
setTimeOffset(70);
|
||||
|
||||
// Try to create a new client session for the same user session
|
||||
withRealm(realmId, (session, realm) -> {
|
||||
ClientModel client = realm.getClientByClientId(CLIENT0_CLIENT_ID);
|
||||
UserSessionModel uSession = session.sessions().getUserSession(realm, uSessionId.get());
|
||||
assertThat(uSession.getAuthenticatedClientSessions(), anEmptyMap());
|
||||
assertThat(session.sessions().createClientSession(realm, client, uSession), notNullValue());
|
||||
return null;
|
||||
});
|
||||
|
||||
// Check session does not contain a reference to expired client session
|
||||
assertCacheContains(remoteCache -> {
|
||||
HotRodUserSessionEntity hotRodUserSessionEntity = remoteCache.get(uSessionId.get());
|
||||
assertThat(hotRodUserSessionEntity.authenticatedClientSessions, hasSize(1));
|
||||
});
|
||||
}
|
||||
|
||||
private void assertCacheContains(Consumer<RemoteCache<String, HotRodUserSessionEntity>> checker) {
|
||||
withRealm(realmId, (session, realm) -> {
|
||||
HotRodConnectionProvider provider = session.getProvider(HotRodConnectionProvider.class);
|
||||
|
|
Loading…
Reference in a new issue