Session Expiration Not Working

I’m trying to implement 15 minute inactivity timeout in my CUBA web application. Per the documentation, I set each of the following properties:

  • cuba.userSessionExpirationTimeoutSec = 900
  • cuba.httpSessionExpirationTimeoutSec = 900

Unfortunately, it is not working. I logged in one User and left them idle for up to an hour, but still their session remained active. I logged in Admin in a different browser in order to monitor User Sessions. I could see the other User’s Session’s Last Used On timestamp being updated despite the fact that they weren’t actually doing anything in the system. Around those same times, I consistently saw the following activity in the application log:

  • [ScheduledRunnerThread-5/app-core/admin] - Start processing queue
  • [ScheduledRunnerThread-5/app-core/admin] - 0 queue items successfully processed
  • [http-nio-8080-exec-40] com.haulmont.cuba.web.App - Ping session
  • [http-nio-8080-exec-38/app/admin] com.haulmont.cuba.web.App - Ping session

Since I see my scheduled FTS Indexing task in that logging, I tried deactivating it and that’s when I finally had success. However, it’s not consistent. I’ve done quite a bit of testing, but only once did I actually experience an expired session. All the other tests I’ve done have not succeeded, regardless of whether the scheduled task is active or not.

Does anyone have any idea why sessions aren’t expiring as expected?

Turns out, the Ping Session logging above is the reason the Session is staying open, and it works that way by design. The heartbeat is used to keep Sessions open while UIs are still open. Closing the browser causes the Session to expire as expected. However, my requirement is to timeout the User after 15 minutes of inactivity, even if the UI is open…

I’ve been digging into the Vaadin documentation and found that setting the closeIdleSessions parameter in web.xml is supposed to cause timeout regardless of whether the UI is open. So I set that, and found that it does work to expire the UI, however the UserSession is still active. I had another requirement to prevent multiple UserSessions for a single User. Since I’ve already implemented that, the User is unable to sign back in until the UserSession expires. That doesn’t happen until the timeout period is reached again (given the properties above, that would be 900 sec after the UI expires).

How can I ensure that the UI and the UserSession both expire at the same time?

I’ve figured it out. Instead of setting the closeIdleSessions parameter to true, I needed to disable heartbeat altogether by setting the heartbeatInterval parameter to -1 in web.xml.

This effectively turns off heartbeat functionality, which seems really counterintuitive given the fact that the Vaadin documentation indicates that this is how to keep sessions alive forever. But digging into CUBA’s source, I found that a UserSession is expired based on lastUsedTs, which is updated with each heartbeat [see UserSessions.processEviction()]. That’s why the UserSession didn’t get removed until another full timeout period after the heartbeat that killed the VaadinSession.

1 Like