Skip to content

Fix reset-token/session interaction in the auth React layer - #9

Merged
jonahc44 merged 1 commit into
mainfrom
claude/fix-reset-token-auth-gate
Jul 20, 2026
Merged

jonahc44 merged 1 commit into
mainfrom
claude/fix-reset-token-auth-gate

Conversation

@jonahc44

Copy link
Copy Markdown
Collaborator

Bugs (reported on a live published Bool)

  1. After a successful password reset, logging out bounces back to "create a new password" instead of the sign-in screen.
  2. Clicking a fresh reset link while already signed in (e.g. from a previous reset, which signs you in on the new password) silently auto-logs in instead of prompting for a new password.

Root cause

useSignInForm read ?bool_reset_token= from the URL on mount and forced mode = "newPassword" — but never removed it from the URL, and it only ran inside AuthGate's fallback branch. AuthGate picks fallback vs children purely on session presence, with zero awareness of the token.

  • (1): the token stayed in the URL forever. Signing out clears the session → AuthGate re-renders fallbackuseSignInForm remounts → its effect re-reads the still-present token → forces newPassword again.
  • (2): AuthGate sees user truthy and renders children immediately; useSignInForm (and its token-reading effect) never mounts, so the token is silently ignored.

Fix

Lift the reset-token capture into BoolAuthProvider (an ancestor of both AuthGate and useSignInForm) as pendingResetToken on context, consumed and stripped from the URL exactly once via a pure, unit-tested helper (takeResetTokenFromSearch).

  • AuthGate now forces fallback when a reset token is pending, even over an active session — a reset link is an explicit ask to set a new password, so it must always reach that screen.
  • useSignInForm reads the same context value instead of independently reading the URL, and clears it on successful confirmReset or when the visitor backs out of newPassword mode (e.g. "Back to sign in") — so AuthGate stops forcing it afterward.

Note on reach

src/react.tsx is unchanged since the initial 0.1.0 release — this bug has shipped to every already-created app on the stable ^0.1.0 range, not just the 0.2.0-next entities-canary line currently on main. Merging this into main alone won't reach those apps: npm's caret rule on a 0.x version pins the minor, so ^0.1.0 never resolves to 0.2.0-next.x. Flagged separately — no 0.1.2 backport is included in this PR.

Tests

Added unit tests for takeResetTokenFromSearch (token extraction/stripping while preserving sibling params) — the pure logic the fix depends on. The provider/gate DOM interaction isn't exercisable in this repo's current SSR-only test setup (no jsdom), same boundary the existing react.test.tsx already draws.

bun run typecheck clean, bun test → 61 pass (was 57).

🤖 Generated with Claude Code

… and an active session skips it entirely

Two symptoms traced to one root cause in the auth React layer:

1. After a successful password reset, logging out bounces back to
   "create a new password" instead of the sign-in screen.
2. Clicking a fresh reset link while already signed in (e.g. from a
   previous reset, which signs you in on the new password) silently
   auto-logs in instead of prompting for a new password.

Root cause: useSignInForm read `?bool_reset_token=` from the URL on mount
and forced mode="newPassword", but never removed it from the URL — and it
only ran inside AuthGate's `fallback` branch, which AuthGate picks purely
on session presence, with zero awareness of the token.

- (1): the token stayed in the URL forever. Signing out clears the
  session -> AuthGate re-renders `fallback` -> useSignInForm remounts ->
  its effect re-reads the still-present token -> forces newPassword again.
- (2): AuthGate sees `user` truthy and renders `children` immediately;
  useSignInForm (and its token-reading effect) never mounts, so the token
  is silently ignored.

Fix: lift the reset-token capture into BoolAuthProvider (an ancestor of
both AuthGate and useSignInForm) as `pendingResetToken` on context,
consumed and stripped from the URL exactly once via a pure, unit-tested
helper (`takeResetTokenFromSearch`). AuthGate now forces `fallback` when a
reset token is pending, even over an active session — a reset link is an
explicit ask to set a new password, so it must always reach that screen.
useSignInForm reads the same context value instead of independently
reading the URL, and clears it on successful confirmReset or when the
visitor backs out of newPassword mode (so AuthGate stops forcing it).

react.tsx is unchanged since the initial 0.1.0 release, so this affects
every already-created app on the stable ^0.1.0 range, not just the
0.2.0-next canary line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jonahc44
jonahc44 merged commit 52b846d into main Jul 20, 2026
3 checks passed
@jonahc44
jonahc44 deleted the claude/fix-reset-token-auth-gate branch July 20, 2026 20:20
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.

1 participant