Skip to content

Warn users before destructive password reset#568

Open
AnthonyRonning wants to merge 2 commits into
masterfrom
aead-password-reset-warning
Open

Warn users before destructive password reset#568
AnthonyRonning wants to merge 2 commits into
masterfrom
aead-password-reset-warning

Conversation

@AnthonyRonning

@AnthonyRonning AnthonyRonning commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a confirmation dialog before requesting password reset, warning that reset creates a new private key and deletes private encrypted data
  • add delayed guidance on the reset-code form for users who may have signed in with Apple, Google, or GitHub instead of password login

Testing

  • nix develop -c bun run --cwd frontend format:check
  • pre-commit hook: bun build
  • pre-commit hook: bun test

Open in Devin Review

Summary by CodeRabbit

  • New Features
    • Added a confirmation warning dialog before initiating password reset requests (Cancel/Continue, disabled while processing).
    • Added an informational guidance alert that appears after ~30 seconds if a reset code hasn't arrived, shown above the Reset Code input.
    • Improved flow to move users into the confirmation step and preserve progress; post-reset redirect to login still occurs.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 21569cc3-2e16-4c80-a015-6729645aea6a

📥 Commits

Reviewing files that changed from the base of the PR and between caf178c and 639392f.

📒 Files selected for processing (2)
  • frontend/src/components/PasswordResetConfirmForm.tsx
  • frontend/src/components/PasswordResetRequestForm.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/components/PasswordResetRequestForm.tsx
  • frontend/src/components/PasswordResetConfirmForm.tsx

📝 Walkthrough

Walkthrough

Two password reset components are updated to improve user experience: PasswordResetRequestForm adds a confirmation warning dialog that gates the reset initiation and refactors reset logic into a dedicated async function, while PasswordResetConfirmForm introduces a timed alert that displays helpful guidance if the reset code fails to arrive within 30 seconds.

Changes

Password Reset Flow Enhancement

Layer / File(s) Summary
Reset request confirmation dialog
frontend/src/components/PasswordResetRequestForm.tsx
AlertDialog-based warning is added to gate reset requests. Form submission now opens the dialog instead of immediately resetting; reset logic moves into a separate requestPasswordReset function that generates secrets, hashes them, and calls os.requestPasswordReset. Continue action triggers the reset with loading state management.
Reset code arrival guidance alert
frontend/src/components/PasswordResetConfirmForm.tsx
Informational alert with Info icon displays after 30-second timeout (while reset is pending) to guide users when reset codes don't arrive. New showCodeHelp state and useEffect timer control alert visibility above the reset code input; existing success-to-login redirect behavior is preserved.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit hops through password gates,
With warnings first, then patient waits,
If codes are slow, a helpful cheer,
"The reset's sent—we're listening here!"
Confirmation guards the flow,
So users always, surely know. 🔐

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Warn users before destructive password reset' directly describes the main change: adding a confirmation warning dialog before password reset in PasswordResetRequestForm, which is the primary modification affecting user interaction.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch aead-password-reset-warning

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

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 10, 2026

Copy link
Copy Markdown

Deploying maple with  Cloudflare Pages  Cloudflare Pages

Latest commit: 639392f
Status: ✅  Deploy successful!
Preview URL: https://374dce02.maple-ca8.pages.dev
Branch Preview URL: https://aead-password-reset-warning.maple-ca8.pages.dev

View logs

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/PasswordResetRequestForm.tsx (1)

30-41: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Capture the submitted email before starting the async reset.

Line 39 sends whatever email was when the request started, but Lines 72-78 still let the user edit that state while the request is in flight. If they change the field before the promise resolves, the reset email goes to one address and the confirm step proceeds with another. Persist the submitted email in separate state and render the confirmation flow from that snapshot; disabling the input during loading will prevent the drift as well.

Suggested fix
 export function PasswordResetRequestForm() {
   const [email, setEmail] = useState("");
+  const [requestedEmail, setRequestedEmail] = useState("");
   const [isLoading, setIsLoading] = useState(false);
   const [error, setError] = useState<string | null>(null);
   const [showConfirmForm, setShowConfirmForm] = useState(false);
   const [showResetWarning, setShowResetWarning] = useState(false);
   const [secret, setSecret] = useState("");
   const os = useOpenSecret();
 
   const requestPasswordReset = async () => {
+    const nextEmail = email;
+
     setIsLoading(true);
     setError(null);
     setShowResetWarning(false);
+    setRequestedEmail(nextEmail);
 
     try {
       // TODO: move this logic to the library
       const generatedSecret = generateSecureSecret();
       const hashedSecret = await hashSecret(generatedSecret);
-      await os.requestPasswordReset(email, hashedSecret);
+      await os.requestPasswordReset(nextEmail, hashedSecret);
       setSecret(generatedSecret);
       setShowConfirmForm(true);
@@
   if (showConfirmForm) {
-    return <PasswordResetConfirmForm email={email} secret={secret} />;
+    return <PasswordResetConfirmForm email={requestedEmail} secret={secret} />;
   }
@@
                 <Input
                   id="email"
                   type="email"
                   value={email}
                   onChange={(e) => setEmail(e.target.value)}
+                  disabled={isLoading}
                   required
                 />

Also applies to: 72-78

🤖 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 `@frontend/src/components/PasswordResetRequestForm.tsx` around lines 30 - 41,
The requestPasswordReset flow uses the live email state which can be edited
while the async call is in-flight, causing a mismatch between the address that
receives the reset and the one used in the confirm UI; fix by capturing a
snapshot of the email before awaiting: set a new state like submittedEmail (use
a setter such as setSubmittedEmail) to the current email immediately at the
start of requestPasswordReset, use that submittedEmail when rendering the
confirmation flow and when calling os.requestPasswordReset, and also disable the
email input while isLoading is true (or until setShowConfirmForm is set) to
prevent further edits during the request.
🤖 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.

Inline comments:
In `@frontend/src/components/PasswordResetConfirmForm.tsx`:
- Around line 39-47: The delayed help timer in PasswordResetConfirmForm's
useEffect currently only checks success and can show the "No code yet?" alert
after the user has entered a code; update the effect to also check that code is
empty (e.g., if (success || code) return), add code to the dependency array, and
ensure you call setShowCodeHelp(false) when code becomes non-empty and
clearTimeout(timer) in cleanup; apply the same gating and cleanup fix to the
other identical effect/logic around lines 101-111 so the help only appears while
the reset code field is empty.

---

Outside diff comments:
In `@frontend/src/components/PasswordResetRequestForm.tsx`:
- Around line 30-41: The requestPasswordReset flow uses the live email state
which can be edited while the async call is in-flight, causing a mismatch
between the address that receives the reset and the one used in the confirm UI;
fix by capturing a snapshot of the email before awaiting: set a new state like
submittedEmail (use a setter such as setSubmittedEmail) to the current email
immediately at the start of requestPasswordReset, use that submittedEmail when
rendering the confirmation flow and when calling os.requestPasswordReset, and
also disable the email input while isLoading is true (or until
setShowConfirmForm is set) to prevent further edits during the request.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 616f8be2-0338-459b-954b-9ad41c2868a4

📥 Commits

Reviewing files that changed from the base of the PR and between 281031f and caf178c.

📒 Files selected for processing (2)
  • frontend/src/components/PasswordResetConfirmForm.tsx
  • frontend/src/components/PasswordResetRequestForm.tsx

Comment thread frontend/src/components/PasswordResetConfirmForm.tsx Outdated
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