Skip to content

1.8.4: verify the session before logging out on 401 so mislabeled permission errors no longer kick authenticated users out#4

Merged
NicoKaempf merged 1 commit into
mainfrom
fix/restrict-401-logout-to-auth-context
Jul 13, 2026
Merged

1.8.4: verify the session before logging out on 401 so mislabeled permission errors no longer kick authenticated users out#4
NicoKaempf merged 1 commit into
mainfrom
fix/restrict-401-logout-to-auth-context

Conversation

@DKoenig9

Copy link
Copy Markdown
Contributor

Problem

The client auth interceptor treats every 401 from a non-auth endpoint as an expired session: clearUser() + hard redirect to the login page. Backends may mislabel permission errors (authenticated user, missing rights — semantically 403) as 401. In that combination a mere missing right kicks a logged-in user out of the whole app.

Observed in production-like usage with @lenne.tech/nest-server ≤ 11.27.6, whose service-layer rights checks (checkRights / checkRestricted) threw 401 for authenticated users (fixed upstream in nest-server PR 11.28.0: throw 403 instead of 401 for permission errors of authenticated users).

Fix

handleUnauthorized() now probes the session endpoint before clearing state (GET <apiBase>/get-session via the JWT-aware fetchWithAuth):

Probe result Action
Session alive (user/session in response) Keep the user logged in — the 401 was a permission error, not an expiry
Session dead (non-OK response or Better Auth's null body) Logout + redirect as before
Probe not completable (network error / API unreachable) Keep the user logged in — an unreachable API is not a logout

Recursion-safe: the probe URL matches the existing auth-endpoint ignore list (/session), and isHandling401 is held while the probe runs.

This is complementary to the nest-server 403 fix and effective against any backend that still sends 401 for permission errors.

Tests

  • New test/auth-interceptor.test.ts (6 cases: alive → no logout, dead via null body → logout, dead via rejection → logout, probe error → no logout, auth endpoints ignored, unauthenticated ignored)
  • Red-green verified: the two "keep logged in" cases fail against the old interceptor
  • Full suite 116/116, vue-tsc (root + playground) and module build green

🤖 Generated with Claude Code

…mission errors no longer kick authenticated users out

The client auth interceptor treated EVERY 401 from a non-auth endpoint as an
expired session: clearUser() + hard redirect to login. Backends may mislabel
permission errors (authenticated user, missing rights - semantically 403) as
401, so a mere missing right threw logged-in users out of the app.

The interceptor now probes the session endpoint (GET /get-session via the
JWT-aware fetchWithAuth) before clearing state:
- session alive   -> keep the user logged in (permission error, no logout)
- session dead    -> logout + redirect as before (real expiry)
- probe undecided -> keep the user logged in (API unreachable != logged out)

Recursion-safe: the probe URL matches the auth-endpoint ignore list and
isHandling401 is held while it runs. Companion fix to lenneTech/nest-server
(checkRights & friends now throw 403 for authenticated users), but effective
against any backend that still sends 401 for permission errors.

Tests: new test/auth-interceptor.test.ts (6 cases incl. red-green against the
old behavior); suite 116/116, vue-tsc + build green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens the client-side auth interceptor so that a 401 from non-auth (“domain”) endpoints no longer automatically logs out authenticated users; instead, it probes the session endpoint first to distinguish real session expiry from mislabeled permission errors.

Changes:

  • Added a session-liveness probe (GET <apiBase>/get-session) and updated 401 handling to only clear auth state when the session is confirmed dead.
  • Added a dedicated Vitest suite covering the new 401 handling behaviors and guard cases.
  • Bumped package version to 1.8.4.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/runtime/plugins/auth-interceptor.client.ts Adds session verification before logout on 401, reducing accidental logouts from mislabeled permission errors.
test/auth-interceptor.test.ts Introduces tests validating session-probe outcomes and ensuring auth endpoints / unauthenticated states are ignored.
package.json Version bump to 1.8.4.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/runtime/plugins/auth-interceptor.client.ts
Comment thread test/auth-interceptor.test.ts
@NicoKaempf
NicoKaempf merged commit 58c74e7 into main Jul 13, 2026
2 checks passed
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.

3 participants