Skip to content

fix(clerk-js): Prevent session cookie removal during offline token refresh#7912

Open
bratsos wants to merge 5 commits intomainfrom
alexbratsos/user-4744-investigate-random-sign-outs-in-the-dashboard-possibly
Open

fix(clerk-js): Prevent session cookie removal during offline token refresh#7912
bratsos wants to merge 5 commits intomainfrom
alexbratsos/user-4744-investigate-random-sign-outs-in-the-dashboard-possibly

Conversation

@bratsos
Copy link
Member

@bratsos bratsos commented Feb 23, 2026

Description

When offline, two code paths in Session.ts emit token:update events with empty tokens. AuthCookieService interprets empty tokens as signed-out and removes the __session cookie — even though the session is still valid server-side. On the next page load or visibility change, the missing cookie makes the user appear signed out.

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

Summary by CodeRabbit

  • Bug Fixes

    • Prevented unexpected sign-outs by avoiding caching or dispatching empty tokens when offline, preserving stale tokens and adding offline-aware retry/error signaling.
  • Tests

    • Added and updated tests for offline retries, background refresh timing, deduplication, and recovery-from-offline to ensure no incorrect token events.
  • Chores

    • Added a changeset entry for the patch.

@changeset-bot
Copy link

changeset-bot bot commented Feb 23, 2026

🦋 Changeset detected

Latest commit: 2c09e1e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@clerk/clerk-js Patch
@clerk/chrome-extension Patch
@clerk/expo Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Feb 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Mar 2, 2026 4:10pm

Request Review

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 23, 2026

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7912

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7912

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7912

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7912

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7912

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7912

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@7912

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7912

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7912

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7912

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@7912

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7912

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7912

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7912

@clerk/react

npm i https://pkg.pr.new/@clerk/react@7912

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7912

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7912

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7912

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7912

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@7912

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7912

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7912

commit: 2c09e1e


describe('with offline browser and network failure', () => {
beforeEach(() => {
// Use real timers for offline tests to avoid unhandled rejection issues with retry logic
Copy link
Member

Choose a reason for hiding this comment

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

🎉

@bratsos bratsos force-pushed the alexbratsos/user-4744-investigate-random-sign-outs-in-the-dashboard-possibly branch from d134aeb to c230146 Compare February 25, 2026 12:05
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a changeset entry for a patch release. Updates packages/clerk-js/src/core/resources/Session.ts to import ClerkRuntimeError and add offline-aware logic: _getToken, _fetchToken, _dispatchTokenEvents, and background refresh now avoid caching or dispatching empty tokens and surface offline as explicit errors to trigger retry behavior. Updates packages/clerk-js/src/core/resources/__tests__/Session.test.ts to adjust timer usage, rename and rework offline-retry tests, and add tests covering offline failures, background-refresh edge cases, recovery mid-request, and timer-driven refresh behavior. No public API signatures changed.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main bug fix: preventing session cookie removal during offline token refresh operations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@bratsos bratsos force-pushed the alexbratsos/user-4744-investigate-random-sign-outs-in-the-dashboard-possibly branch from 992a3ba to 2377201 Compare February 25, 2026 18:04
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/clerk-js/src/core/resources/Session.ts`:
- Around line 451-453: The token-update path currently emits and caches/clears
when isValidBrowserOnline() is true even if cachedToken.getRawString() is empty;
change the guard so eventBus.emit(events.TokenUpdate, { token: cachedToken })
and any code that writes/clears __session only run when
cachedToken.getRawString() is truthy (i.e., require a non-empty token), and do
not rely on isValidBrowserOnline() as a substitute for a missing token. Apply
this same change to the other TokenUpdate/caching occurrences that use
cachedToken.getRawString() || isValidBrowserOnline() so all places (the
eventBus.emit call and the __session write/clear logic) first check
cachedToken.getRawString() before proceeding.

ℹ️ Review info

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2377201 and fd118d9.

📒 Files selected for processing (2)
  • packages/clerk-js/src/core/resources/Session.ts
  • packages/clerk-js/src/core/resources/__tests__/Session.test.ts

@bratsos bratsos force-pushed the alexbratsos/user-4744-investigate-random-sign-outs-in-the-dashboard-possibly branch from 745dbbe to 2c09e1e Compare March 2, 2026 16:09
Comment on lines +76 to +81
// navigator.onLine is the standard API and is reliable for detecting
// complete disconnection (airplane mode, WiFi off, etc.).
// The experimental navigator.connection API (rtt/downlink) was previously
// used as a secondary signal, but it reports zero values in headless browsers
// and CI environments even when connected, causing false offline detection.
return !!navigator.onLine;
Copy link
Member

Choose a reason for hiding this comment

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

hmm, I'm not sure we want to change this. can we look back in the history? I feel like I recall there being issues with only relying on navigator.onLine in the past

Copy link
Member Author

Choose a reason for hiding this comment

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

I couldn't find something concrete - the main difference is that navigator.onLine can return true even when there's no actual internet connectivity (it only detects whether the device is connected to a network, for example a wifi network with no internet access).

navigator.connection seems like a better signal but it's more unreliable as it's not supported on Firefox or Safari at all, in headless browsers it reports navigator.connection.rtt == 0 and I found other issues around the web as well.

This seems the better fix and we can always iterate. WDYT?

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.

3 participants