Fix unexpected expiration when import offline client session
Closes #23397
This commit is contained in:
parent
31759f9c37
commit
eedc4ceb18
2 changed files with 60 additions and 0 deletions
|
@ -1063,6 +1063,9 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
|
|||
AuthenticatedClientSessionEntity entity = createAuthenticatedClientSessionInstance(clientSession,
|
||||
sessionToImportInto.getRealm().getId(), clientSession.getClient().getId(), offline);
|
||||
|
||||
// Update timestamp to same value as userSession. LastSessionRefresh of userSession from DB will have correct value
|
||||
entity.setTimestamp(sessionToImportInto.getLastSessionRefresh());
|
||||
|
||||
if (checkExpiration) {
|
||||
SessionFunction<AuthenticatedClientSessionEntity> lifespanChecker = offline
|
||||
? SessionTimeouts::getOfflineClientSessionLifespanMs : SessionTimeouts::getClientSessionLifespanMs;
|
||||
|
|
|
@ -49,8 +49,10 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -413,6 +415,61 @@ public class UserSessionProviderOfflineModelTest extends KeycloakModelTest {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadingOfflineClientSessionWhenCreatedBeforeSessionTime() {
|
||||
// setup idle timeout for the realm
|
||||
int idleTimeout = (int) TimeUnit.DAYS.toSeconds(1);
|
||||
withRealm(realmId, (session, realmModel) -> {
|
||||
realmModel.setClientOfflineSessionIdleTimeout(idleTimeout);
|
||||
return null;
|
||||
});
|
||||
|
||||
// create online user and client sessions
|
||||
inComittedTransaction((Consumer<KeycloakSession>) session -> UserSessionPersisterProviderTest.createSessions(session, realmId));
|
||||
|
||||
// create offline user and client sessions
|
||||
List<String> offlineUserSessionIds = withRealm(realmId, (session, realm) -> session.sessions()
|
||||
.getUserSessionsStream(realm, realm.getClientByClientId("test-app"))
|
||||
.map(userSession -> {
|
||||
UserSessionModel offlineUserSession = Optional.ofNullable(
|
||||
session.sessions().getOfflineUserSession(realm, userSession.getId())
|
||||
).orElseGet(() -> session.sessions().createOfflineUserSession(userSession));
|
||||
|
||||
userSession.getAuthenticatedClientSessions()
|
||||
.values()
|
||||
.forEach(clientSession -> {
|
||||
// set timestamp manually to make sure the client session is created before session time
|
||||
// this simulates the cases when the offline client sessions are created before the session time
|
||||
clientSession.setTimestamp(Time.currentTime() - idleTimeout * 2);
|
||||
|
||||
session.sessions().createOfflineClientSession(clientSession, offlineUserSession);
|
||||
});
|
||||
|
||||
return offlineUserSession.getId();
|
||||
}
|
||||
).collect(Collectors.toList())
|
||||
);
|
||||
|
||||
withRealm(realmId, (session, realm) -> {
|
||||
// remove offline client sessions from the cache
|
||||
// this simulates the cases when offline client sessions are lost from the cache due to various reasons (a cache limit/expiration/preloading issue)
|
||||
session.getProvider(InfinispanConnectionProvider.class)
|
||||
.getCache(InfinispanConnectionProvider.OFFLINE_CLIENT_SESSION_CACHE_NAME).clear();
|
||||
|
||||
String clientUUID = realm.getClientByClientId("test-app").getId();
|
||||
|
||||
offlineUserSessionIds.forEach(id -> {
|
||||
UserSessionModel offlineUserSession = session.sessions().getOfflineUserSession(realm, id);
|
||||
|
||||
// each associated offline client session should be found by looking into persister
|
||||
AuthenticatedClientSessionModel offlineClientSession = offlineUserSession.getAuthenticatedClientSessionByClient(clientUUID);
|
||||
Assert.assertNotNull(offlineClientSession);
|
||||
Assert.assertEquals(offlineUserSession.getLastSessionRefresh(), offlineClientSession.getTimestamp());
|
||||
});
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private static Set<String> createOfflineSessionIncludeClientSessions(KeycloakSession session, UserSessionModel
|
||||
userSession) {
|
||||
Set<String> offlineSessions = new HashSet<>();
|
||||
|
|
Loading…
Reference in a new issue