UI Session Management
DRAFT DRAFT DRAFT DRAFT DRAFT
UI Session Management
Session management is complicated. In the simplest case, a person logs in (receiving a token in the form of cookies to start their session), does some work, and logs out (destroying their cookies to end their session). In a less complicated case, a person logs in, does some work, and then their session ends without them explicitly choosing to end it. This could happen for several different reasons:
Refresh Token Rotation (RTR) errors: the UI receives a response from an API request indicating the session is corrupt or compromised.
Idle Session Timeout (IST): a timer in the UI (measuring the time since last activity) has expired.
Fixed-length Session Timeout (FLST): a timer in the UI (measuring the time since authentication) has expired.
While RTR, IST, and FLST feel like closely-related UI issues, in fact they are largely independent. RTR and FLST use timers on the frontend but are configured on the backend. Only IST is both implemented and configured on the frontend.
Under the hood: timers and tokens
This section explains the technical implementation of RTR and FLST. The details are not important, though they will provide some clarity; the important thing is to have a high-level understanding of how these tokens and timers affect a user's session.
When a user authenticates, the UI makes an API request with their username and password. If these credentials are correct, the API response contains two tokens in the form of cookies:
an access-token (AT) with a short lifespan (~10 minutes) that is sent along with ordinary API requests (e.g. to retrieve items or PO lines or patron records) and can be used on multiple requests
a refresh token (RT) with a long lifespan (hours to days) that is sent only with refresh API requests to retrieve new tokens and can be used only once
RTR is the periodic, background process of renewing the AT before it expires. When the UI receives an AT/RT pair, it starts a timer that expires 80% of the way through the AT's lifecycle. When the timer expires, the UI sends an API request to /authn/refresh; the response contains new tokens that overwrite the old tokens. The AT’s expiration extends forward, creating a "sliding window". In Okapi, the RT's expiration is also calculating on sliding window. In Eureka the RT’s expiration is fixed (thus, FLST). Visually, it looks a bit like this:
// Okapi Sliding window session timeout (SWST)
|---------|---------|---------|---------|
at1-------|
rt1-------------------------------------|
at2-------|
rt2-------------------------------------|
at3-------|
rt3-------------------------------------|
// Eureka fixed length session timeout (FLST)
|---------|---------|---------|---------|
at1-------|
rt1-------------------------------------|
at2-------|
rt2---------------------------|
at3-------|
rt3-----------------|
Note that a side-effect of SWST is that a session can be perpetually extended as long as the RT is exchanged before it expires (the length of the window is fixed but the expiration date is perpetually extended). This may be considered a convenience or a security flaw depending on your perspective. FLST tightens security (the endpoint of the session is fixed and the length of the RT window shrinks each time it is refreshed).
RTR
RTR is a background process. It is completely hidden from the UI under ordinary circumstances. A correctly-functioning browser will never send the same RT twice, so the backend interprets a repeated request as a security violation. When this happens, the backend immediately invalidates all tokens for that user and sends an error response to the rotation request. On receiving an error response to a rotation request, the UI will terminate the session and redirect to /logout.
Configuration
In Okapi, AT and RT expirations are configured on the backend in mod-authtoken. See the mod-authtoken README for details. The AT defaults to 10 minutes. The RT defaults to 7 days.
In Eureka, AT and RT expirations are configured on the backend in Keycloak. See RTR Configuration on Eureka for details. Typically, the AT is set to 10 minutes and the RT to 1 day.
Timeouts
When a session begins, the UI sets two timers:
Idle-Session Timeout: this timer tracks the elapsed time since the last activity (e.g. keyclicks or mouseclicks) and is continually reset with each event. It is implemented as a sliding window; the events and the length of the timeout are configured when the UI is built in
stripes.config.js.Fixed-Length-Session Timeout: this timer tracks the elapsed time since the RT was renewed and is reset when the RT rotates using the expiration value of the RT in the API response. Thus, whether this timer operates as a sliding-window or a fixed-window depends on how the backend is configured. Okapi uses a sliding window. Eureka uses a fixed window.
Idle-session timeout
Idle-session timeout is a UI-only feature that tracks browser events and terminates the session if a fixed period of inactivity elapses. Each time the UI receives a new event, it resets the timer, sliding the window forward. Code and configuration for this feature exist exclusively in the UI. When the idle-session timer trips, the UI shows an interactive "Keep working?" modal with a countdown timer. When the timer hits 00:00, the UI will terminate the session and redirect to /logout-timeout. Clicking the "Keep working" button dismisses the modal and resets the timer.
Configuration
IST is configured on the frontend when the UI bundle is built. See stripes.config.js properties for details. The following default values are configurable:
idle session timeout, i.e. how long before an idle session is killed: 4 hours
idle modal timeout, i.e. how long to show the "keep working?" modal: 1 minute
events that are interpreted as activity: keydown, mousedown
Fixed-length-session timeout
Fixed-length-session timeout is implemented in the UI but configured in the backend. When the UI receives an RT (i.e., after authentication or after token rotation), it sets a timer to expire when the RT expires, replacing the previous FLST timer. Code for this feature exists in both the UI (to set the UI timer) and the backend (to set the expiration date for the RTs); configuration is in the backend (Okapi uses mod-authtoken and a sliding-window; Eureka uses Keycloak and a fixed-window). When the fixed-length-session timer expires, the UI shows a non-interactive "Session expiration" warning banner with a countdown timer. The banner cannot be dismissed and has no "Keep working?" button because the session cannot be extended. When the timer hits 00:00; the UI will terminate the session and redirect to /logout-timeout.
Configuration
RT expiration is configured on the backend as described above, either in mod-authtoken or in Keycloak. The only aspect of FLST configurable on the frontend is how long the "Session expiration" warning banner is displayed. See stripes.config.js properties for details; the default is 1 minute.
Examples
Okapi, 4h IST, 7d SWST: if a user begins work on Monday at 09:00 and works throughout the day, leaving at 17:00, and returns to work on Tuesday at 08:00, their session will have expired overnight due to IST and they'll have to login again. If they do something interactive every 4h, their session will never expire. This configuration means most users would have to log in once at the beginning of each day and may or may not experience IST during the day. Users will never encounter FLST.
Okapi, 1d IST, 1d SWST: if a user begins work on Monday at 09:00 and works throughout the day, leaving at 17:00, and returns to work on Tuesday at 08:00, their session will have continued through the night. If they do something interactive every 1d, their session will never expire. This configuration means most users would log in once at the beginning of each week, and their sessions would expire over the weekends. Users will never encounter FLST.
Eureka, 4h IST, 1d FLST: if a user begins work on Monday at 09:00 and works throughout the day, leaving at 17:00, and returns to work on Tuesday at 08:00, their session will have expired overnight due to IST and they'll have to login again. This configuration means most users would have to log in once at the beginning of each day and may or may not experience IST during the day. Under ordinary working circumstances, users will never experience FLST with this configuration.
Eureka, 1d IST, 1d FLST: if a user begins work on Monday at 09:00 and works throughout the day, leaving at 17:00, and returns to work on Tuesday at 08:00, their session will have continued through the night. After 1 hour of work, the session will end due to FLST regardless of the user's activity and they will be forced to log in again. This configuration means most users would have to log in once each day, and will interact with FLST on any day when they begin work on FOLIO earlier than when their FOLIO session began on the previous day.