Skip to content

Warn user when credentials have expired in multiuser mode#134

Draft
Copilot wants to merge 17 commits intomainfrom
copilot/enhance-multiuser-token-warning
Draft

Warn user when credentials have expired in multiuser mode#134
Copilot wants to merge 17 commits intomainfrom
copilot/enhance-multiuser-token-warning

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 4, 2026

In multiuser mode, expired JWT tokens caused the app to silently stop working with no user-facing explanation. Users now get redirected to the login page with a clear expiration message.

Changes

  • authSlice.ts: Added sessionExpired: boolean state field and sessionExpiredLogout action (sets sessionExpired = true + clears auth). setCredentials and logout both reset sessionExpired = false. Added selectSessionExpired selector. sessionExpired excluded from redux-persist.

  • api/index.ts: dynamicBaseQuery now intercepts 401 responses on non-auth endpoints when a token is present, dispatching sessionExpiredLogout(). Existing ProtectedRoute auth-guard logic handles the redirect automatically.

  • ProtectedRoute.tsx: Switched from logout to sessionExpiredLogout when initial user fetch fails (handles stale token in localStorage on page load).

  • LoginPage.tsx: Renders a warning banner when sessionExpired is true"Your credentials have expired. Please log in again to resume."

  • en.json: Added auth.login.sessionExpired translation key.

Related Issues / Discussions

QA Instructions

  1. Enable multiuser mode and log in.
  2. Manually expire the token (delete/corrupt auth_token in localStorage, or wait for expiry and make an API call).
  3. Verify redirect to /login with the expiration warning banner visible.
  4. Log in again — confirm the banner is gone and the app works normally.

Merge Plan

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

Copilot AI linked an issue Apr 4, 2026 that may be closed by this pull request
1 task
Copilot AI changed the title [WIP] Enhance multiuser support to warn users on expired credentials Warn user when credentials have expired in multiuser mode Apr 4, 2026
Copilot AI requested a review from lstein April 4, 2026 15:06
Backend:
- SlidingWindowTokenMiddleware refreshes JWT on each mutating request
  (POST/PUT/PATCH/DELETE), returning a new token in X-Refreshed-Token
  response header. GET requests don't refresh (they're often background
  fetches that shouldn't reset the inactivity timer).
- CORS expose_headers updated to allow X-Refreshed-Token.

Frontend:
- dynamicBaseQuery picks up X-Refreshed-Token from responses and
  updates localStorage so subsequent requests use the fresh expiry.
- 401 handler only triggers sessionExpiredLogout when a token was
  actually sent (not for unauthenticated background requests).
- ProtectedRoute polls localStorage every 5s and listens for storage
  events to detect token removal (e.g. manual deletion, other tabs).

Result: session expires after TOKEN_EXPIRATION_NORMAL (1 day) of
inactivity, not a fixed time after login. Any user-initiated action
resets the clock.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions bot added the python label Apr 4, 2026
lstein and others added 2 commits April 4, 2026 14:01
Bug fixes:
- ProtectedRoute: only treat 401 errors as session expiry, not
  transient 500/network errors that should not force logout
- Token refresh: use explicit remember_me claim in JWT instead of
  inferring from remaining lifetime, preventing silent downgrade of
  7-day tokens to 1-day when <24h remains
- TokenData: add remember_me field, set during login

Tests (6 new):
- Mutating requests (POST/PUT/DELETE) return X-Refreshed-Token
- GET requests do not return X-Refreshed-Token
- Unauthenticated requests do not return X-Refreshed-Token
- Remember-me token refreshes to 7-day duration even near expiry
- Normal token refreshes to 1-day duration
- remember_me claim preserved through refresh cycle

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
JPPhoto and others added 7 commits April 4, 2026 16:48
* Upgrade spandrel to 0.4.2 in uv.lock

* Fixed typos
* Fix workflow copy hotkeys in info view

* Fix Makefile help target copy

* Fix workflow info view copy handling

* Fix workflow edge delete hotkeys
Co-authored-by: dunkeroni <dunkeroni@gmail.com>
* Run vitest during frontend build

* Add frontend-test Make target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[enhancement]: Warn user when their credentials have expired

5 participants