Details
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientUserSessionAssociationEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientUserSessionAssociationEntity.java
index 3c38142..7fa4011 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientUserSessionAssociationEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientUserSessionAssociationEntity.java
@@ -22,8 +22,7 @@ import javax.persistence.NamedQuery;
@NamedQuery(name = "getActiveClientSessions", query = "select COUNT(s) from ClientUserSessionAssociationEntity s where s.clientId = :clientId"),
@NamedQuery(name = "removeClientUserSessionByClient", query = "delete from ClientUserSessionAssociationEntity s where s.clientId = :clientId"),
@NamedQuery(name = "removeClientUserSessionByUser", query = "delete from ClientUserSessionAssociationEntity s where s.user = :user"),
- @NamedQuery(name = "removeClientUserSessionByRealm", query = "delete from ClientUserSessionAssociationEntity s where s.realm = :realm")
-})
+ @NamedQuery(name = "removeClientUserSessionByRealm", query = "delete from ClientUserSessionAssociationEntity s where s.realm = :realm")})
public class ClientUserSessionAssociationEntity {
@Id
@GenericGenerator(name="uuid_generator", strategy="org.keycloak.models.jpa.utils.JpaIdGenerator")
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserSessionEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserSessionEntity.java
index 976df2f..28ea9fb 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserSessionEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserSessionEntity.java
@@ -23,6 +23,7 @@ import java.util.Collection;
@NamedQuery(name = "getUserSessionByUser", query = "select s from UserSessionEntity s where s.user = :user"),
@NamedQuery(name = "removeRealmUserSessions", query = "delete from UserSessionEntity s where s.realm = :realm"),
@NamedQuery(name = "removeUserSessionByUser", query = "delete from UserSessionEntity s where s.user = :user"),
+ @NamedQuery(name = "getUserSessionExpired", query = "select s from UserSessionEntity s where s.started < :maxTime or s.lastSessionRefresh < :idleTime"),
@NamedQuery(name = "removeUserSessionExpired", query = "delete from UserSessionEntity s where s.started < :maxTime or s.lastSessionRefresh < :idleTime")
})
public class UserSessionEntity {
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index 95e5ed0..b3eb12f 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -1450,10 +1450,13 @@ public class RealmAdapter implements RealmModel {
@Override
public void removeExpiredUserSessions() {
- em.createNamedQuery("removeUserSessionExpired")
+ TypedQuery<UserSessionEntity> query = em.createNamedQuery("getUserSessionExpired", UserSessionEntity.class)
.setParameter("maxTime", Time.currentTime() - getSsoSessionMaxLifespan())
- .setParameter("idleTime", Time.currentTime() - getSsoSessionIdleTimeout())
- .executeUpdate();
+ .setParameter("idleTime", Time.currentTime() - getSsoSessionIdleTimeout());
+ List<UserSessionEntity> results = query.getResultList();
+ for (UserSessionEntity entity : results) {
+ em.remove(entity);
+ }
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
index 4051a6e..bebe763 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
@@ -190,6 +190,43 @@ public class AdapterTest {
realm.setSsoSessionIdleTimeout(originalIdle);
keycloakRule.stopSession(providerSession, true);
}
+
+ @Test
+ public void testLoginSSOIdleRemoveExpiredUserSessions() throws Exception {
+ // test login to customer-portal which does a bearer request to customer-db
+ driver.navigate().to("http://localhost:8081/customer-portal");
+ System.out.println("Current url: " + driver.getCurrentUrl());
+ Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
+ loginPage.login("bburke@redhat.com", "password");
+ System.out.println("Current url: " + driver.getCurrentUrl());
+ Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/customer-portal");
+ String pageSource = driver.getPageSource();
+ System.out.println(pageSource);
+ Assert.assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen"));
+
+ ProviderSession providerSession = keycloakRule.startSession();
+ RealmModel realm = providerSession.getProvider(KeycloakSession.class).getRealmByName("demo");
+ int originalIdle = realm.getSsoSessionIdleTimeout();
+ realm.setSsoSessionIdleTimeout(1);
+ keycloakRule.stopSession(providerSession, true);
+
+ Thread.sleep(2000);
+
+ providerSession = keycloakRule.startSession();
+ realm = providerSession.getProvider(KeycloakSession.class).getRealmByName("demo");
+ realm.removeExpiredUserSessions();
+ keycloakRule.stopSession(providerSession, true);
+
+ // test SSO
+ driver.navigate().to("http://localhost:8081/product-portal");
+ Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
+
+ providerSession = keycloakRule.startSession();
+ realm = providerSession.getProvider(KeycloakSession.class).getRealmByName("demo");
+ realm.setSsoSessionIdleTimeout(originalIdle);
+ keycloakRule.stopSession(providerSession, true);
+ }
+
@Test
public void testLoginSSOMax() throws Exception {
// test login to customer-portal which does a bearer request to customer-db