In the aim to implement a synchronous per user/per group max sessions limitation, I do manage to retrieve login events using EventListenerProvider keycloak SPI as described here But from the user I would need to retrieve the list of sessions, online and offline
The provided API seems to give access to that sessions and to allow deletion of it, as described in this example.
But in my case it returns no sessions at all, either in version 11.0.3, 19.0.1 or 20.01
@JBossLog
public class PhoenixEventListenerProvider implements EventListenerProvider {
private final KeycloakSession keycloakSession;
private final KeycloakContext keycloakContext;
private final RealmProvider realmProvider;
private final ClientProvider clientProvider;
private final UserSessionProvider userSessionProvider;
private static String clientRealm = "myRealm";
public PhoenixEventListenerProvider(KeycloakSession keycloakSession) {
this.keycloakSession = keycloakSession;
this.keycloakContext = keycloakSession.getContext();
this.realmProvider = keycloakSession.realms();
this.clientProvider = keycloakSession.clients();
this.userSessionProvider = keycloakSession.sessions();
}
/**
* https://www.keycloak.org/docs-api/20.0.2/javadocs/org/keycloak/models/UserSessionProvider.html#getUserSession(org.keycloak.models.RealmModel,java.lang.String)
*
* @param event
*/
@Override
public void onEvent(Event event) {
if (event.getType().name().toUpperCase().contains("LOGIN") && event.getRealmId().equals(clientRealm)) {
RealmModel realmM = keycloakContext.getRealm();
ClientModel clientM = keycloakContext.getClient();
String userId = event.getUserId();
long offlineSessionsCount = userSessionProvider.getOfflineSessionsCount(realmM,clientM);
long nbActiveUserSessions = userSessionProvider.getActiveUserSessions(realmM,clientM);
UserSessionModel userSessionModel = userSessionProvider.getUserSession(realmM,userId);
UserSessionModel offlineUserSessionModel = userSessionProvider.getOfflineUserSession(realmM,userId);
String result= MessageFormat.format(
"nbActiveUserSessions: {0}\n" +
"offlineSessionsCount: {1}\n" +
"userSessionModel.getId(): {2}\n" +
"offlineUserSessionModel.getId(): {3}\n",
Long.toString(nbActiveUserSessions),
Long.toString(offlineSessionsCount),
userSessionModel.getId(),
offlineUserSessionModel.getId()
);
log.info(result);
}
}
}`
after login of a user the event is received, but result is 0 for nbActiveUserSessions,offlineSessionsCount and returned ids ar null.
nbActiveUserSessions: 0
offlineSessionsCount: 0
userSessionModel: null
offlineUserSessionModel: null
Would you know how to retrieve the sessions , whithout using any asynchronous call like if using the REST API ?
Apparently, the new session is created after the LOGIN event, so the list of session available are the already existing ones. If necessary, another SPI should probably be used to act on the session beeing created .
Would you plane to limit the number of sessions through this interface, you will only be able to invalidate previous sessions and as a consequence, you will have to solve the problem of valid token still living in the browser or the clients maintaining their ability to use the intended services.
Implementing SPI org.keycloak.authentication.Authenticator is a better solution since it is called before authentication success.