Skip to content

feat: handle session expiry#61

Closed
kabaros wants to merge 2 commits intomainfrom
session-handler
Closed

feat: handle session expiry#61
kabaros wants to merge 2 commits intomainfrom
session-handler

Conversation

@kabaros
Copy link
Collaborator

@kabaros kabaros commented Feb 15, 2026

This PR adds ability to gracefully handle session expiry on the frontend.

  • This PR uses a frontend-driven approach, listening to API calls from apps and starting a session timer that resets with every API call.
  • This works in conjunction with this change in the app-shell: feat: notify the global shell of apps API calls app-platform#952
    • It means that for it to work we should bump the app-shell version in all apps
    • The app shell patches fetch API in order to send a message whenever an API is called
    • The global shell then listens to these notifications and resets the session timer
    • It also listens to receiving a 401 specifically and shows the session expiry
  • It addresses cross-window instances of the applications by using a BroadCastChannel , so if any window receives a 401, the session expiry modal is shown in all DHIS2 instances running on the same host.

ToDos

  • Ensure the session handler doesn't kick in in the Login app

The issue with a backend-driven approach

The first commit in this branch uses an approach based on the backend returning a cookie with the time stamp for when the cookie expires. This has some issues:

  • The backend returns a time stamp indicating when the session would expire. The frontend then uses the time stamp to calculate the remaining time in the session and when it expires - this makes a major assumption: that clients' times are set correctly. I don't think this is an assumption that we can make safely and relying on a browser setting for something as important seems risky to me.
  • Listening to cookie changes is not straightforward - we can continuously poll it which comes with issues (JS timers are non-deterministic, and browsers halt them on inactive tabs). We could use the CookieStore API to avoid these issues (but need to investigate how to make it work in non-https contexts for development).

The only canonical signal for a session expiry is a 401 - everything else is an workaround. I think that's the one thing a solution should handle (then the timers, notifications and so on are nice to have).

In the global-shell context (of apps being hosted in an iframe), I can't think of a different approach of capturing 401s other than the solution here. But in general, I think this should be our approach - to detect 401s and handle them, rather than trying to infer that they happened.

Notes:

  • Showing a session expiry modal when a 401 is encountered is a very accurate, and a robust indication of session expiry. It is hard to implement the countdown timer in a way that is as accurate and works across windows. We'd have to either broadcast all API calls (not only 401s) to all windows in order to keep the timers in sync. But this might be acceptable since the worst case scenario would be that one window will expire (and broadcast that it expired) and the other windows will, at least, show the session expiry modal (but skip the countdown) - that's still a good-enough experience imo.
Screencast.from.2026-02-15.16-10-29.webm

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
6 New issues
6 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@kabaros kabaros requested a review from KaiVandivier February 15, 2026 17:50
@kabaros kabaros closed this Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant