Skip to content

feat: add biometric auth for password-gated flows#2182

Merged
Nick-1979 merged 16 commits into
mainfrom
addFingerPrintToPasswordField
Jun 4, 2026
Merged

feat: add biometric auth for password-gated flows#2182
Nick-1979 merged 16 commits into
mainfrom
addFingerPrintToPasswordField

Conversation

@Nick-1979

@Nick-1979 Nick-1979 commented Jun 2, 2026

Copy link
Copy Markdown
Member

closes #2164

Summary by CodeRabbit

  • New Features

    • Broad biometric support added: account creation/derivation, import, export (single & batch), change-password-all, and removal confirmation; new biometric action hook and biometric-aware messaging.
  • UI/Style

    • Password inputs now show biometric controls and improved spacing/visibility; snackbar layout adjusted; modal background visuals refined.
  • Bug Fix

    • Forget-account flow no longer clears biometric enrollment if other local accounts remain.
  • Documentation

    • Validation guidance expanded; new i18n key added.

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

Integrates biometric authentication across account flows by adding request types, backend biometric handlers and routing, a frontend biometric hook and messaging wrappers, biometric UI controls in PasswordInput, and wiring across create/import/derive/export/remove/manage-password. Also adjusts accountsForget biometric cleanup and updates AGENTS.md.

Changes

Biometric Authentication Feature

Layer / File(s) Summary
Type contracts and backend message handlers
packages/extension-base/src/utils/biometric.ts, packages/extension-base/src/background/types.ts, packages/extension-base/src/background/handlers/Extension.ts
Adds RequestBiometricAuthentication, extends RequestSignatures with biometric message IDs, changes accountsForget cleanup rule, and implements withBiometricPassword plus biometric-wrapped handlers and routing.
Frontend biometric hook and utilities
packages/extension-polkagate/src/hooks/useBiometricAction.ts, packages/extension-polkagate/src/hooks/index.ts, packages/extension-polkagate/src/util/biometric.ts, packages/extension-polkagate/src/messaging.ts
Introduces useBiometricAction, authenticateWithBiometric, and biometric messaging wrappers for create/derive/export/change-password-all.
PasswordInput component and UI tweaks
packages/extension-polkagate/src/components/PasswordInput.tsx, packages/extension-polkagate/src/components/MySnackbar.tsx, packages/extension-polkagate/src/components/MatchPasswordField.tsx, packages/extension-polkagate/src/fullscreen/components/DraggableModal.tsx
Adds biometric button/props to PasswordInput, visibility-toggle gating, small snackbar and modal styling changes, and refines MatchPasswordField setter type.
Account creation and import with biometric
packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts, packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/index.tsx, packages/extension-polkagate/src/popup/import/importSeedFullScreen/index.tsx, packages/extension-polkagate/src/popup/import/importRawSeedFullScreen/index.tsx
Tracks biometric auth in the hook, branches creation between password and biometric, wires biometric props/handlers, and enables actions when password or biometric validation is present.
Account derivation with biometric parent validation
packages/extension-polkagate/src/fullscreen/home/DeriveAccount/index.tsx, packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx, packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ChildInfo.tsx, packages/extension/public/locales/en/translation.json
Threads biometric-validated state, validates parent/derivation via password or biometric, and derives child accordingly; adds a translation key.
Account management operations with biometric
packages/extension-polkagate/src/partials/RemoveAccount.tsx, packages/extension-polkagate/src/popup/settings/accountSettings/Export.tsx, packages/extension-polkagate/src/popup/settings/extensionSettings/ManagePassword.tsx
Enables biometric confirmation for removal, biometric export (single/batch), and biometric-assisted password change.

Sequence Diagram

sequenceDiagram
  participant Screen as UI Screen
  participant Hook as useBiometricAction
  participant Msg as messaging.ts
  participant Bg as Extension.handle
  participant Store as EnrollmentStore
  Screen->>Hook: runBiometricAction(action)
  Hook->>Screen: isBiometricBusy=true
  Hook->>Msg: action(auth from authenticateWithBiometric)
  Msg->>Bg: pri(...biometric..., {credentialId, prfOutput, ...})
  Bg->>Store: lookup enrollment / decrypt password
  Bg-->>Msg: result (boolean|export json|false)
  Msg-->>Screen: resolves action result
  Hook->>Screen: isBiometricBusy=false
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PolkaGate/extension#2163: Touches biometric enrollment cleanup in Extension.ts, overlapping with accountsForget behavior here.
  • PolkaGate/extension#2096: Modifies ManagePassword flow related to password changes, intersecting with this PR’s biometric-assisted path.
  • PolkaGate/extension#2151: Related edits to RemoveAccount/forgetAccount flow that overlap with biometric confirmation changes.

Suggested labels

change requested

Suggested reviewers

  • AMIRKHANEF

Poem

🐇 Tap, tap — a secret’s scan,
Keys unlock without a hand.
From seed to child, from vault to door,
Exports fly, passwords restore.
A whisker twitch, a gentle byte—
Hop, approve, and all’s set right. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.68% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately and concisely describes the main change: adding biometric authentication support to password-gated flows throughout the application.
Linked Issues check ✅ Passed The PR comprehensively implements biometric authentication across all eligible password-gated flows including account creation, import, derivation, export, password management, and account removal, fulfilling issue #2164.
Out of Scope Changes check ✅ Passed Minor styling adjustments to MySnackbar and DraggableModal appear unrelated to biometric auth but are incidental UI improvements; all substantive changes align with the biometric authentication objectives.

✏️ 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 addFingerPrintToPasswordField

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 and usage tips.

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Add biometric authentication support for password-gated operations

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add biometric authentication support for password-gated operations
  - New RequestBiometricAuthentication type for credential-based auth
  - Biometric variants for account export, batch export, and password change
  - Biometric variants for account creation and derivation operations
• Implement useBiometricAction hook for unified biometric flow management
• Enhance PasswordInput component with fingerprint icon and biometric verification UI
• Extend messaging layer with biometric-enabled API functions
• Update account removal and password management flows to support biometric auth
Diagram
flowchart LR
  A["User Action<br/>Export/Create/Derive"] --> B["PasswordInput<br/>with Biometric"]
  B --> C{Auth Method}
  C -->|Password| D["Traditional<br/>Password Flow"]
  C -->|Biometric| E["useBiometricAction<br/>Hook"]
  E --> F["authenticateWithBiometric<br/>Get PRF Output"]
  F --> G["RequestBiometricAuthentication<br/>credentialId + prfOutput"]
  D --> H["Extension Handler<br/>Process Request"]
  G --> H
  H --> I["withBiometricPassword<br/>Decrypt & Execute"]
  I --> J["Operation Complete<br/>Export/Create/Derive"]

Loading

Grey Divider

File Changes

1. packages/extension-base/src/background/handlers/Extension.ts ✨ Enhancement +78/-3

Add biometric authentication handlers for account operations

packages/extension-base/src/background/handlers/Extension.ts


2. packages/extension-base/src/background/types.ts ✨ Enhancement +38/-1

Define biometric request/response types for new operations

packages/extension-base/src/background/types.ts


3. packages/extension-base/src/utils/biometric.ts ✨ Enhancement +5/-0

Add RequestBiometricAuthentication interface

packages/extension-base/src/utils/biometric.ts


View more (16)
4. packages/extension-polkagate/src/hooks/index.ts ✨ Enhancement +1/-0

Export new useBiometricAction hook

packages/extension-polkagate/src/hooks/index.ts


5. packages/extension-polkagate/src/hooks/useBiometricAction.ts ✨ Enhancement +56/-0

Implement biometric action hook for unified auth flow

packages/extension-polkagate/src/hooks/useBiometricAction.ts


6. packages/extension-polkagate/src/messaging.ts ✨ Enhancement +25/-1

Add biometric-enabled messaging functions for operations

packages/extension-polkagate/src/messaging.ts


7. packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts ✨ Enhancement +55/-14

Support biometric authentication in account creation flow

packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts


8. packages/extension-polkagate/src/util/biometric.ts ✨ Enhancement +10/-1

Add authenticateWithBiometric function for PRF output

packages/extension-polkagate/src/util/biometric.ts


9. packages/extension-polkagate/src/components/MySnackbar.tsx Formatting +2/-3

Adjust snackbar styling for better layout

packages/extension-polkagate/src/components/MySnackbar.tsx


10. packages/extension-polkagate/src/components/PasswordInput.tsx ✨ Enhancement +83/-20

Add fingerprint icon and biometric verification UI

packages/extension-polkagate/src/components/PasswordInput.tsx


11. packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ChildInfo.tsx ✨ Enhancement +26/-17

Support biometric authentication in account derivation

packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ChildInfo.tsx


12. packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx ✨ Enhancement +98/-24

Add biometric validation for parent account in derivation

packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx


13. packages/extension-polkagate/src/fullscreen/home/DeriveAccount/index.tsx ✨ Enhancement +6/-2

Thread biometric validation state through derivation flow

packages/extension-polkagate/src/fullscreen/home/DeriveAccount/index.tsx


14. packages/extension-polkagate/src/partials/RemoveAccount.tsx ✨ Enhancement +36/-6

Enable biometric authentication for account removal

packages/extension-polkagate/src/partials/RemoveAccount.tsx


15. packages/extension-polkagate/src/popup/import/importRawSeedFullScreen/index.tsx ✨ Enhancement +15/-6

Support biometric auth in raw seed import flow

packages/extension-polkagate/src/popup/import/importRawSeedFullScreen/index.tsx


16. packages/extension-polkagate/src/popup/import/importSeedFullScreen/index.tsx ✨ Enhancement +12/-3

Support biometric auth in seed import flow

packages/extension-polkagate/src/popup/import/importSeedFullScreen/index.tsx


17. packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/index.tsx ✨ Enhancement +13/-4

Support biometric auth in account creation UI

packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/index.tsx


18. packages/extension-polkagate/src/popup/settings/accountSettings/Export.tsx ✨ Enhancement +37/-4

Add biometric authentication option for account export

packages/extension-polkagate/src/popup/settings/accountSettings/Export.tsx


19. packages/extension-polkagate/src/popup/settings/extensionSettings/ManagePassword.tsx ✨ Enhancement +61/-4

Enable biometric authentication for password management

packages/extension-polkagate/src/popup/settings/extensionSettings/ManagePassword.tsx


Grey Divider

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Jun 2, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📎 Requirement gaps (0) 🎨 UX issues (0)

Grey Divider


Action required

1. Biometric wrapper hides errors ✓ Resolved 🐞 Bug ≡ Correctness
Description
Extension.withBiometricPassword catches and converts all errors (including errors thrown by the
wrapped action) into false, which destroys error semantics for flows like derivation validation.
As a result, invalid derivation paths can be misreported as password failures and the UI never
receives the thrown message needed to set the correct derivation-path error.
Code

packages/extension-base/src/background/handlers/Extension.ts[R487-507]

Evidence
The background derivation code throws specific errors for password vs path, but the new biometric
wrapper converts any thrown error into false. The ParentInfo biometric path handles false by
marking the password invalid and never enters the catch that sets pathError, so path errors are
misclassified.

packages/extension-base/src/background/handlers/Extension.ts[487-507]
packages/extension-base/src/background/handlers/Extension.ts[529-531]
packages/extension-base/src/background/handlers/Extension.ts[1045-1058]
packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx[89-107]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`withBiometricPassword` wraps the provided `action` in a broad try/catch and returns `false` on any exception. This means action-specific exceptions (e.g., derivation path validation throwing a path error) are swallowed and indistinguishable from biometric/auth failures.

### Issue Context
- `derive(...)` throws different errors for invalid password vs invalid derivation path.
- `derivationBiometricValidate` calls `derivationValidate` through `withBiometricPassword`, so both errors become `false`.
- UI code (ParentInfo) treats a `false` result as a password error, and only sets the derivation-path error message in the `catch` block (which won't run if the background returns `false`).

### Fix Focus Areas
- packages/extension-base/src/background/handlers/Extension.ts[487-507]
- packages/extension-base/src/background/handlers/Extension.ts[529-536]
- packages/extension-base/src/background/handlers/Extension.ts[1045-1058]
- packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx[89-107]

### Suggested fix
Option A (recommended):
- Only catch biometric/enrollment/decryption failures and return `false` for those.
- Let `action(...)` exceptions propagate (rethrow) so the messaging layer rejects the Promise and existing UI `catch` blocks can show correct error messages.

Option B:
- Return a discriminated union instead of `T | false` (e.g., `{ ok:false, reason:'biometric_failed' } | { ok:true, value:T }`) and update UI accordingly.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Unnecessary validateSeed refactor 📘 Rule violation ⚙ Maintainability
Description
validateSeed was refactored from async to returning Promise.resolve(...) without changing
behavior, which is not required to implement biometric auth. This is an out-of-scope refactor that
increases PR noise.
Code

packages/extension-polkagate/src/popup/import/importRawSeedFullScreen/index.tsx[R41-53]

Evidence
The checklist requires limiting refactoring/format-only changes to what is necessary for the
requested feature and ensuring changed lines map to a documented request. The updated validateSeed
implementation only changes how the same value is wrapped in a Promise.

Rule 660842: Limit refactoring to changes required by the task scope
Rule 660844: Changed lines must be justified by a documented user or stakeholder request
packages/extension-polkagate/src/popup/import/importRawSeedFullScreen/index.tsx[41-53]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`validateSeed` was refactored (async removal + `Promise.resolve`) without any functional need for biometric auth.

## Issue Context
PR scope is biometric auth for password-gated flows; this change appears to be cosmetic/cleanup and not required for the feature.

## Fix Focus Areas
- packages/extension-polkagate/src/popup/import/importRawSeedFullScreen/index.tsx[41-53]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unrelated MySnackbar style tweaks 📘 Rule violation ⚙ Maintainability
Description
The PR modifies MySnackbar layout styles (icon sx and typography padding) even though the
documented request is biometric auth for password-gated flows. This adds unrelated formatting churn
and makes the change set harder to review and audit.
Code

packages/extension-polkagate/src/components/MySnackbar.tsx[R106-118]

Evidence
The checklist requires avoiding unrelated formatting/adjacent-code churn and ensuring changed lines
are traceable to an explicit request. The changed MySnackbar lines adjust UI spacing/positioning
without any apparent connection to the biometric-password feature.

Rule 660840: Avoid unrelated changes to adjacent code and formatting
Rule 660844: Changed lines must be justified by a documented user or stakeholder request
packages/extension-polkagate/src/components/MySnackbar.tsx[106-118]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`MySnackbar` style/layout changes were included in a biometric-auth PR without any documented need.

## Issue Context
PR scope (title/description) is biometric auth for password-gated flows; these `MySnackbar` changes appear to be cosmetic and unrelated.

## Fix Focus Areas
- packages/extension-polkagate/src/components/MySnackbar.tsx[106-118]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Biometric errors unhandled 🐞 Bug ☼ Reliability
Description
useBiometricAction.runBiometricAction lets authenticateWithBiometric exceptions propagate, and
some call sites (e.g., RemoveAccount and account create/import) await it without try/catch, so
cancellation/unsupported-PRF errors can become unhandled promise rejections with no user-facing
error state. This makes biometric-gated flows brittle and hard to debug.
Code

packages/extension-polkagate/src/hooks/useBiometricAction.ts[R35-48]

Evidence
runBiometricAction calls authenticateWithBiometric without catching exceptions.
authenticateWithBiometric throws when PRF output cannot be produced, and at least two PR-modified
call sites await runBiometricAction without any try/catch, so those exceptions can escape the
React event handler boundary.

packages/extension-polkagate/src/hooks/useBiometricAction.ts[19-49]
packages/extension-polkagate/src/util/biometric.ts[121-149]
packages/extension-polkagate/src/util/biometric.ts[253-259]
packages/extension-polkagate/src/partials/RemoveAccount.tsx[179-194]
packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts[140-152]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`runBiometricAction` does not handle failures from `authenticateWithBiometric` (WebAuthn prompt cancellation, PRF unavailable, DOMExceptions). Some callers don't wrap `runBiometricAction(...)` in `try/catch`, which can lead to unhandled promise rejections and missing UI error feedback.

### Issue Context
- `authenticateWithBiometric` ultimately calls `navigator.credentials.get(...)` and can throw when PRF output is unavailable.
- Call sites like RemoveAccount and account create/import currently assume `runBiometricAction` resolves to `undefined` on failure, but it can throw instead.

### Fix Focus Areas
- packages/extension-polkagate/src/hooks/useBiometricAction.ts[35-49]
- packages/extension-polkagate/src/partials/RemoveAccount.tsx[179-194]
- packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts[140-152]

### Suggested fix
- Add a `catch` inside `runBiometricAction` that logs (or reports) the error and returns `undefined` (or a typed failure) so callers can reliably handle failures without needing try/catch everywhere.
- Optionally still allow callers to detect cancellation vs other failures by returning a discriminated result (e.g., `{ ok:false, reason:'cancelled'|'unsupported'|'error' }`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread packages/extension-base/src/background/handlers/Extension.ts

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

Actionable comments posted: 8

Caution

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

⚠️ Outside diff range comments (1)
packages/extension-polkagate/src/partials/RemoveAccount.tsx (1)

134-161: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't report removal success when forgetAccount returns false.

forgetAccount returns a boolean, but Lines 160-161 notify success and close the modal even when that call fails. In that case the account stays in place while the UI tells the user it was removed.

Suggested fix
       const success = await forgetAccount(_address);

-      if (success) {
-        if (accountsAssets?.balances?.[_address]) {
-          const latestStoredAssets = await getStorage(STORAGE_KEY.ASSETS, true).catch(() => undefined) as SavedAssets | undefined;
-          const baseAssets = latestStoredAssets?.balances ? latestStoredAssets : accountsAssets;
-          const updatedAssets: SavedAssets = {
-            ...baseAssets,
-            balances: { ...baseAssets.balances }
-          };
-
-          delete updatedAssets.balances[_address];
-          setAccountsAssets(updatedAssets);
-          await setStorage(STORAGE_KEY.ASSETS, updatedAssets, true);
-        }
-
-        await Promise.allSettled([
-          cleanupNotificationAccount(_address),
-          cleanupAuthorizedAccount(_address)
-        ]);
-
-        if (willProfileBeEmpty) {
-          setStorage(STORAGE_KEY.SELECTED_PROFILE, PROFILE_TAGS.ALL).catch(console.error);
-        }
-      }
-
-      notifier(true);
-      !isExtension && handleClose(); // in full-screen mode, close the modal on success
+      if (!success) {
+        throw new Error('Unable to remove account');
+      }
+
+      if (accountsAssets?.balances?.[_address]) {
+        const latestStoredAssets = await getStorage(STORAGE_KEY.ASSETS, true).catch(() => undefined) as SavedAssets | undefined;
+        const baseAssets = latestStoredAssets?.balances ? latestStoredAssets : accountsAssets;
+        const updatedAssets: SavedAssets = {
+          ...baseAssets,
+          balances: { ...baseAssets.balances }
+        };
+
+        delete updatedAssets.balances[_address];
+        setAccountsAssets(updatedAssets);
+        await setStorage(STORAGE_KEY.ASSETS, updatedAssets, true);
+      }
+
+      await Promise.allSettled([
+        cleanupNotificationAccount(_address),
+        cleanupAuthorizedAccount(_address)
+      ]);
+
+      if (willProfileBeEmpty) {
+        setStorage(STORAGE_KEY.SELECTED_PROFILE, PROFILE_TAGS.ALL).catch(console.error);
+      }
+
+      notifier(true);
+      !isExtension && handleClose(); // in full-screen mode, close the modal on success
🤖 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 `@packages/extension-polkagate/src/partials/RemoveAccount.tsx` around lines 134
- 161, The code calls notifier(true) and handleClose() unconditionally even when
forgetAccount(_address) returned false; move the success UI actions inside the
success branch: after the existing if (success) { ... } block, call
notifier(true) and !isExtension && handleClose() only when success is true (and
optionally call notifier(false) on the failure path); update references to
forgetAccount, notifier, handleClose, setAccountsAssets, setStorage,
cleanupNotificationAccount and cleanupAuthorizedAccount so the UI success/close
behavior is gated by the success boolean.
🤖 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 `@packages/extension-polkagate/src/components/PasswordInput.tsx`:
- Around line 175-186: The IconButton rendering the biometric action (controlled
by onBiometricClick) is not keyboard-accessible because it explicitly sets
tabIndex={-1}; remove that tabIndex (or set it to default) so the IconButton
(and its onClick handler handleBiometricClick / FingerScan icon) can receive
focus and be activated by keyboard when not disabled (biometricDisabled ||
isBiometricBusy), restoring keyboard access to the biometric path while
preserving existing disabled logic and aria-labels.
- Around line 88-96: The onChange handler in PasswordInput should preserve the
existing cleared semantics by calling onPassChange with an empty string (''),
not null, when the input is cleared—keep onPassChange typed as (pass: string) =>
void and ensure the onChange path (the function using setHasPasswordValue and
setShowPassword) passes '' for empty values so consumers that check falsy
behavior continue to work; also fix keyboard reachability for the biometric
IconButton in PasswordInput by removing tabIndex={-1} (or set it to 0) and
wiring a keyboard handler (e.g., onKeyDown/Enter/Space) that invokes the same
biometric action as the click handler so the IconButton is focusable and
operable via keyboard.

In
`@packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ChildInfo.tsx`:
- Around line 55-67: Clear any previous error before starting the derivation,
and ensure the snackbar is opened for both success and failure paths: at start
of the handler call setError('') to avoid stale messages, then if derivation
succeeds call setError('') (or set a success message) and setShowSnackbar(true);
in the catch block setError(error instanceof Error ? error.message :
String(error)) and also setShowSnackbar(true) so failures are visible. Update
the flow around deriveAccount / deriveAccountWithBiometric (and
maybeChidAccount.suri) to guarantee error state is cleared before attempting and
that setShowSnackbar(true) is invoked on both success and failure.

In
`@packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx`:
- Around line 62-67: The effect that resets parent biometric state on parent
account change (the useEffect that calls setIsProperParentPassword,
setMaybeChidAccount, setParentBiometricAuth, setParentBiometricValidated) must
also clear the stored parent password to avoid validating with stale
credentials; add a call to clear the parent password state (e.g.,
setParentPassword(undefined) or equivalent setter for parentPassword) inside
that same effect so the old password is removed whenever newParentAddress
changes.

In `@packages/extension-polkagate/src/partials/RemoveAccount.tsx`:
- Around line 179-194: The onBiometricValidate callback should catch rejected
biometric promises: wrap the await runBiometricAction(...) call in a try/catch
inside onBiometricValidate (referencing onBiometricValidate and
runBiometricAction) so that any thrown error sets setPasswordError(true) and
returns, instead of letting the rejection bubble; on success continue to call
setBiometricValidated(true) and setPasswordError(false) as currently
implemented.

In
`@packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/index.tsx`:
- Around line 95-100: The Create account primary button is only disabled based
on password/biometric state which allows a clickable no-op when name is empty;
update the DecisionButtons disabled prop to include name validation (e.g.
disabled={!name || (!password && !isBiometricValidated)}) so the button is
disabled until a non-empty name is provided and authentication is satisfied, and
keep onCreate/onConfirm behavior unchanged.

In
`@packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts`:
- Around line 149-150: The password input is not controlled when biometric mode
clears state via setPassword(undefined), so update the three callers
(SetNameAndPassword, ImportSeed, ImportRawSeed) to render PasswordInput with an
explicit controlled value prop (e.g. value={password ?? ''}) so the UI reflects
the hook state when onBiometricPassword calls setBiometricAuth and setPassword;
locate the useAccountImportOrCreate hook (where setBiometricAuth and setPassword
are called) and the PasswordInput usages in those three components and add
value={password ?? ''} to each PasswordInput.

In
`@packages/extension-polkagate/src/popup/settings/extensionSettings/ManagePassword.tsx`:
- Around line 73-87: Do not set STORAGE_KEY.LAST_PASS_CHANGE until the biometric
password change actually succeeds: move the
setStorage(STORAGE_KEY.LAST_PASS_CHANGE, Date.now()) call to after
accountsChangePasswordAllWithBiometric(...) returns true. In the catch and
failure branches for the biometric flow (where
accountsChangePasswordAllWithBiometric is used), avoid the misleading "Current
password is wrong!" text—use a generic failure message (e.g., "Password change
failed" or "Biometric authentication failed") when calling setSnackbarText, and
keep setting setPasswordError(true), setShowSnackbar(true), and
setMissionSucceeded(false) on failure as before.

---

Outside diff comments:
In `@packages/extension-polkagate/src/partials/RemoveAccount.tsx`:
- Around line 134-161: The code calls notifier(true) and handleClose()
unconditionally even when forgetAccount(_address) returned false; move the
success UI actions inside the success branch: after the existing if (success) {
... } block, call notifier(true) and !isExtension && handleClose() only when
success is true (and optionally call notifier(false) on the failure path);
update references to forgetAccount, notifier, handleClose, setAccountsAssets,
setStorage, cleanupNotificationAccount and cleanupAuthorizedAccount so the UI
success/close behavior is gated by the success boolean.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 04172fcc-a0a6-46c2-924e-342600039299

📥 Commits

Reviewing files that changed from the base of the PR and between a0240c1 and fc1bfb7.

📒 Files selected for processing (19)
  • packages/extension-base/src/background/handlers/Extension.ts
  • packages/extension-base/src/background/types.ts
  • packages/extension-base/src/utils/biometric.ts
  • packages/extension-polkagate/src/components/MySnackbar.tsx
  • packages/extension-polkagate/src/components/PasswordInput.tsx
  • packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ChildInfo.tsx
  • packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx
  • packages/extension-polkagate/src/fullscreen/home/DeriveAccount/index.tsx
  • packages/extension-polkagate/src/hooks/index.ts
  • packages/extension-polkagate/src/hooks/useBiometricAction.ts
  • packages/extension-polkagate/src/messaging.ts
  • packages/extension-polkagate/src/partials/RemoveAccount.tsx
  • packages/extension-polkagate/src/popup/import/importRawSeedFullScreen/index.tsx
  • packages/extension-polkagate/src/popup/import/importSeedFullScreen/index.tsx
  • packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/index.tsx
  • packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts
  • packages/extension-polkagate/src/popup/settings/accountSettings/Export.tsx
  • packages/extension-polkagate/src/popup/settings/extensionSettings/ManagePassword.tsx
  • packages/extension-polkagate/src/util/biometric.ts

Comment thread packages/extension-polkagate/src/components/PasswordInput.tsx
Comment thread packages/extension-polkagate/src/components/PasswordInput.tsx
Comment thread packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx Outdated
Comment thread packages/extension-polkagate/src/partials/RemoveAccount.tsx

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

Caution

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

⚠️ Outside diff range comments (1)
packages/extension-polkagate/src/components/MatchPasswordField.tsx (1)

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

Strengthen minimum password length requirement.

The minimum password length of 1 character is insufficient for security. Industry best practices recommend at least 8-12 characters for password-based authentication. This is especially important in the context of this PR, which adds biometric authentication as an alternative—password-based flows should maintain robust security standards.

🔒 Suggested minimum length increase
-const MINIMUM_ALLOWED_PASSWORD_LENGTH = 1;
+const MINIMUM_ALLOWED_PASSWORD_LENGTH = 8;
🤖 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 `@packages/extension-polkagate/src/components/MatchPasswordField.tsx` at line
32, The MINIMUM_ALLOWED_PASSWORD_LENGTH constant in MatchPasswordField.tsx is
too low; change MINIMUM_ALLOWED_PASSWORD_LENGTH from 1 to a stronger value
(e.g., 8 or 12) and update any related validation logic, UI messages, or tests
that reference this constant (e.g., password length checks in MatchPasswordField
component) so the validation and user feedback reflect the new minimum.
🤖 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.

Outside diff comments:
In `@packages/extension-polkagate/src/components/MatchPasswordField.tsx`:
- Line 32: The MINIMUM_ALLOWED_PASSWORD_LENGTH constant in
MatchPasswordField.tsx is too low; change MINIMUM_ALLOWED_PASSWORD_LENGTH from 1
to a stronger value (e.g., 8 or 12) and update any related validation logic, UI
messages, or tests that reference this constant (e.g., password length checks in
MatchPasswordField component) so the validation and user feedback reflect the
new minimum.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eec3d796-6bcb-449b-a230-245e1d4a6f21

📥 Commits

Reviewing files that changed from the base of the PR and between fc1bfb7 and a97f39d.

📒 Files selected for processing (4)
  • packages/extension-polkagate/src/components/MatchPasswordField.tsx
  • packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts
  • packages/extension-polkagate/src/popup/settings/accountSettings/Export.tsx
  • packages/extension/public/locales/en/translation.json
✅ Files skipped from review due to trivial changes (1)
  • packages/extension/public/locales/en/translation.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/useAccountImportOrCreate.ts
  • packages/extension-polkagate/src/popup/settings/accountSettings/Export.tsx

@Nick-1979

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Caution

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

⚠️ Outside diff range comments (2)
packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx (2)

62-68: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clear pathError when the parent account changes.

This effect swaps suriPath to a fresh default for the new parent, but the old derivation-path error survives because the validator effect only sets errors. That leaves a stale error message visible on an otherwise valid default path.

Suggested fix
   useEffect(() => {
     setIsProperParentPassword(undefined); // reset password error on maybeChidAccount change
     setMaybeChidAccount(undefined);
     setParentBiometricAuth(undefined);
     setParentBiometricValidated(false);
     setParentPassword(undefined);
+    setPathError('');
   }, [newParentAddress, setMaybeChidAccount, setParentBiometricValidated, setParentPassword]);
🤖 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
`@packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx`
around lines 62 - 68, The effect that runs on parent change (the useEffect that
calls setIsProperParentPassword, setMaybeChidAccount, setParentBiometricAuth,
setParentBiometricValidated, setParentPassword) must also clear any stale
derivation-path error and reset the path state: call setPathError(undefined) and
reset suriPath to the fresh default (via the existing setter for suriPath)
inside that same effect so the old pathError doesn’t persist when a new parent
address is selected; update the effect to include these two calls alongside the
other setters.

90-97: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Drop the biometric session when validation is rejected.

If validateDerivationPathWithBiometric(...) returns false, this branch keeps parentBiometricAuth and isParentBiometricValidated set. The UI still shows biometric auth as verified and the next click reuses the same rejected payload instead of forcing a fresh biometric prompt.

Suggested fix
         if (!_account) {
+          setParentBiometricAuth(undefined);
+          setParentBiometricValidated(false);
           setIsProperParentPassword(false);
 
           return;
         }
🤖 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
`@packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx`
around lines 90 - 97, When validateDerivationPathWithBiometric(parentAddress,
suriPath, parentBiometricAuth) returns false, clear the stored biometric session
and mark biometric as not validated so the UI forces a fresh prompt;
specifically, in the branch inside the isParentBiometricValidated &&
parentBiometricAuth check where you call setIsProperParentPassword(false) and
return, also call the state setters that clear parentBiometricAuth and set
isParentBiometricValidated to false (e.g. setParentBiometricAuth(null/undefined)
and setIsParentBiometricValidated(false)) so the rejected payload is dropped and
the next action triggers a new biometric flow.
🤖 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.

Outside diff comments:
In
`@packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx`:
- Around line 62-68: The effect that runs on parent change (the useEffect that
calls setIsProperParentPassword, setMaybeChidAccount, setParentBiometricAuth,
setParentBiometricValidated, setParentPassword) must also clear any stale
derivation-path error and reset the path state: call setPathError(undefined) and
reset suriPath to the fresh default (via the existing setter for suriPath)
inside that same effect so the old pathError doesn’t persist when a new parent
address is selected; update the effect to include these two calls alongside the
other setters.
- Around line 90-97: When validateDerivationPathWithBiometric(parentAddress,
suriPath, parentBiometricAuth) returns false, clear the stored biometric session
and mark biometric as not validated so the UI forces a fresh prompt;
specifically, in the branch inside the isParentBiometricValidated &&
parentBiometricAuth check where you call setIsProperParentPassword(false) and
return, also call the state setters that clear parentBiometricAuth and set
isParentBiometricValidated to false (e.g. setParentBiometricAuth(null/undefined)
and setIsParentBiometricValidated(false)) so the rejected payload is dropped and
the next action triggers a new biometric flow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 83a5b77e-bc56-4082-9924-a06239c18a90

📥 Commits

Reviewing files that changed from the base of the PR and between a97f39d and 764028a.

📒 Files selected for processing (10)
  • AGENTS.md
  • packages/extension-base/src/background/handlers/Extension.ts
  • packages/extension-polkagate/src/components/PasswordInput.tsx
  • packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ChildInfo.tsx
  • packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ParentInfo.tsx
  • packages/extension-polkagate/src/partials/RemoveAccount.tsx
  • packages/extension-polkagate/src/popup/import/importRawSeedFullScreen/index.tsx
  • packages/extension-polkagate/src/popup/import/importSeedFullScreen/index.tsx
  • packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/index.tsx
  • packages/extension-polkagate/src/popup/settings/extensionSettings/ManagePassword.tsx
💤 Files with no reviewable changes (1)
  • packages/extension-polkagate/src/components/PasswordInput.tsx
✅ Files skipped from review due to trivial changes (1)
  • AGENTS.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/extension-polkagate/src/popup/import/importSeedFullScreen/index.tsx
  • packages/extension-polkagate/src/popup/newAccount/createAccountFullScreen/index.tsx
  • packages/extension-base/src/background/handlers/Extension.ts
  • packages/extension-polkagate/src/popup/settings/extensionSettings/ManagePassword.tsx
  • packages/extension-polkagate/src/partials/RemoveAccount.tsx
  • packages/extension-polkagate/src/fullscreen/home/DeriveAccount/ChildInfo.tsx

@Nick-1979 Nick-1979 merged commit 4848935 into main Jun 4, 2026
7 checks passed
@Nick-1979 Nick-1979 deleted the addFingerPrintToPasswordField branch June 4, 2026 20:13
github-actions Bot pushed a commit that referenced this pull request Jun 4, 2026
# [2.12.0](v2.11.0...v2.12.0) (2026-06-04)

### Bug Fixes

* align Subscan requests with free plan limits ([#2183](#2183)) ([eab20df](eab20df))

### Features

* add biometric auth for password-gated flows ([#2182](#2182)) ([4848935](4848935)), closes [#2164](#2164)
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.

Apply fingerprint authentication to all eligible password input flows

1 participant