Repository navigation
fix(auth): unenroll the unverified factor after a failed registration - #2641
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 WalkthroughSummary by CodeRabbit
WalkthroughThe WebAuthn enrollment failure cleanup now matches factors with Assessment against linked issues
Merge Risk: 🔵 Low · up to This change prevents a failed registration from deleting an existing verified passkey, but cleanup can still remove an unrelated unverified passkey with the same name during retries or concurrent registrations. The PR is mergeable with explicit owner awareness and follow-up to bind cleanup to the failed registration. 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. Comment |
@supabase/auth-js
@supabase/functions-js
@supabase/postgrest-js
@supabase/realtime-js
@supabase/storage-js
@supabase/supabase-js
commit: |
mandarini
left a comment
There was a problem hiding this comment.
Hi @Kjubikstronk, thank you for contributing to Supabase! 💚
Fix is correct. FactorVerificationStatuses is a closed union of verified and unverified, so !== 'unverified' was exactly === 'verified'. Good catch, and thanks for keeping the diff to just that.
Two things before merge:
-
Add a comment above the changed line. A one character flip is easy to revert later by mistake. State the invariant: cleanup targets a stale unverified factor so a retry can succeed, and must never select a verified one.
-
Two more tests. Your existing two are solid. Please also cover a verified and an unverified factor sharing a name (verified survives), and no matching factor at all (
unenrollnever called).
Yours is the one we are taking of the PRs for this issue, the tests belong in passkey.methods.test.ts where you put them. Thanks again!
…anup Adds the invariant as a comment above the status check, so the one character is not flipped back by mistake, and two cases the existing tests did not reach: a verified and an unverified factor sharing a friendly name, and no matching factor at all.
|
Both done in 97a16eb. The comment. Above the status check, stating it in terms of what each status means rather than what the operator is: // Only an unverified factor is leftover from the enrollment that just
// failed, and removing it is what lets a retry with the same name
// succeed. A verified factor of that name is a passkey the user is
// already using, so it must never be selected here.The two tests. Both in
I checked the new tests actually bite: reverting the character back to
|
|
@Kjubikstronk i'll fix the |
|
@Kjubikstronk can you please rebase with |
This PR updates `@supabase/supabase-js` to v2.114.0. **Source**: supabase-js-stable-release --- ## Release Notes ## v2.114.0 ## 2.114.0 (2026-09-02) ### 🚀 Features - **storage:** object versioning updates ([#2644](supabase/supabase-js#2644)) ### 🩹 Fixes - **auth:** unenroll the unverified factor after a failed registration ([#2641](supabase/supabase-js#2641)) - **deps:** override browserslist to patch high-severity advisories ([#2652](supabase/supabase-js#2652)) ### ❤️ Thank You - Katerina Skroumpelou @mandarini - Miodrag Obradovic @Kjubikstronk - Tyler Hillery ## v2.113.0 ## 2.113.0 (2026-09-02) ### 🚀 Features - **realtime:** allow wait for pg changes ([#2630](supabase/supabase-js#2630)) ### ❤️ Thank You - Filipe Cabaço @filipecabaco This PR was created automatically. Co-authored-by: supabase-workflow-trigger[bot] <266661614+supabase-workflow-trigger[bot]@users.noreply.github.com>
Closes #2640.
When
_enrollfails,register()tries to clean up after itself by finding a webauthn factor with the same friendly name and unenrolling it. The lookup selects onv.status !== 'unverified', which matches a verified factor, so a failed re-registration can delete a passkey the user already had working.The factor worth cleaning up is the unverified one the failed attempt just left behind, so the condition is inverted. That is the whole change:
Two tests in
passkey.methods.test.ts, which mocks fetch throughout and needs no server. One drives a failed enrollment with an existing verified factor of the same name and assertsunenrollis never called; the other does the same with an unverified factor and asserts it is unenrolled by id. Both fail onmasterand pass with the change, and the other 29 tests in that file are unaffected.prettier --checkis clean on both files.