Skip to content

fix(dexie-cloud-addon): fall back to fetchTokens when refresh fails - #2326

Merged
dfahlander merged 1 commit into
masterfrom
liz/refresh-token-revocation-fallback
Aug 5, 2026
Merged

fix(dexie-cloud-addon): fall back to fetchTokens when refresh fails#2326
dfahlander merged 1 commit into
masterfrom
liz/refresh-token-revocation-fallback

Conversation

@liz709

@liz709 liz709 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Why

Server-side, refresh tokens issued via the client_credentials grant (impersonation) now carry a client_id claim and get checked against that exact internal.clients row on every refresh_token grant exchange — see dexie/dexie-cloud#195. This means a revoked or expired (expires_at) API client's refresh tokens correctly stop working, even though the refresh token's own exp claim can be up to 3650 days out.

Client-side, login() had no recovery path for that case: a locally unexpired refreshTokenExpiration was trusted blindly, and loadAccessToken() throwing on a 401 propagated straight out of login() uncaught.

This matters most for customers using their own fetchTokens config (e.g. a backend that impersonates end-users via client_credentials + claims). If their backend's own API client is later rotated (dexie-cloud rotate) or expires, all of that customer's end-users would previously get an uncaught error on next refresh, with no built-in recovery.

What changed

In login(), a refresh failure (other than an OAuthRedirectError, which means the page is navigating away) now falls through to the exact same re-authentication path already used for the "no refresh token" case — re-running fetchTokens exactly as on first login, instead of throwing.

Practical effect for customers with custom fetchTokens: this becomes self-healing. Their endpoint can either silently re-mint tokens under the hood (if their own session/auth is still valid), or trigger their own challenge/login flow (if not) — same UX as a first-time login.

Testing

  • pnpm build — clean.
  • No existing unit test coverage for login()/the auth flow in this addon's karma suite (only max-unsynced-mutations exists today) — verified via manual trace of the control flow instead. Noting this explicitly rather than claiming test coverage that doesn't exist.
  • CodeRabbit: 0 findings.

Related

  • Server-side change this depends on: dexie/dexie-cloud#195 (adds client_id claim + refresh-token revocation check + dexie-cloud rotate). Recommend releasing together, or at minimum this addon fix before/alongside the server release, so the new server-side enforcement doesn't strand existing custom-auth integrations.

Summary by CodeRabbit

  • Bug Fixes
    • Improved sign-in recovery when a saved session token is missing or fails.
    • Users are now guided through full authentication when session renewal cannot be completed.
    • OAuth redirect errors continue to be handled correctly.

Server-side, refresh tokens issued via client_credentials (impersonation)
now carry a client_id claim and get checked against that client row on
every 'refresh_token' grant (dexie-cloud PR #195) -- so a revoked or
expired API client's refresh tokens correctly stop working, even if the
refresh token's own exp claim (up to 3650 days) hasn't been reached yet.

Client-side, login() had no recovery path for that case: a locally
unexpired refreshTokenExpiration was trusted blindly, and loadAccessToken()
throwing on a 401 propagated straight out of login() uncaught.

Now: a refresh failure (other than an OAuth redirect) falls through to
the same re-authentication path used for 'no refresh token', re-running
fetchTokens exactly as on first login. Customers with their own fetchTokens
(e.g. server-side impersonation-based auth) get self-healing behavior:
either silent re-mint under the hood if their own session is still valid,
or their own challenge/login flow triggered if not -- same as first login.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The login flow now catches refresh-token failures and continues to full re-authentication. It still rethrows OAuthRedirectError. The related message now covers missing and failed refresh tokens.

Changes

Authentication flow

Layer / File(s) Summary
Refresh-token failure handling
addons/dexie-cloud/src/authentication/login.ts
Refresh-token loading returns on success, rethrows OAuthRedirectError, and falls through to full authentication for other failures. The message covers absent and failed refresh tokens.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: falling back to fetchTokens when refresh-token handling fails.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch liz/refresh-token-revocation-fallback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
addons/dexie-cloud/src/authentication/login.ts (1)

42-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression tests for the refresh failure branches.

Add tests that verify:

  • A successful loadAccessToken() returns false and does not invoke fetchTokens.
  • A non-OAuthRedirectError failure invokes the existing authentication path.
  • An OAuthRedirectError is rethrown and does not invoke fetchTokens.

This is a critical authentication recovery path, and the current build does not verify its runtime behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@addons/dexie-cloud/src/authentication/login.ts` around lines 42 - 48, Add
regression tests around the login flow containing loadAccessToken: verify
successful token loading returns false without calling fetchTokens,
non-OAuthRedirectError failures continue into the existing authentication path,
and OAuthRedirectError is rethrown without calling fetchTokens. Use the existing
authentication test setup and mocks, asserting both outcomes and fetchTokens
invocation behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@addons/dexie-cloud/src/authentication/login.ts`:
- Around line 42-48: Add regression tests around the login flow containing
loadAccessToken: verify successful token loading returns false without calling
fetchTokens, non-OAuthRedirectError failures continue into the existing
authentication path, and OAuthRedirectError is rethrown without calling
fetchTokens. Use the existing authentication test setup and mocks, asserting
both outcomes and fetchTokens invocation behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a18b645-1b7a-41dd-bdff-8d3b3a43b6b9

📥 Commits

Reviewing files that changed from the base of the PR and between 962052f and e0f95ea.

📒 Files selected for processing (1)
  • addons/dexie-cloud/src/authentication/login.ts

@dfahlander
dfahlander merged commit 3fd4745 into master Aug 5, 2026
7 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.

2 participants