Skip to content

fix(fxa-settings): route passkey Sync sign-in to password fallback on mobile#20739

Draft
vpomerleau wants to merge 1 commit into
mainfrom
FXA-13911-passkey-sync-mobile
Draft

fix(fxa-settings): route passkey Sync sign-in to password fallback on mobile#20739
vpomerleau wants to merge 1 commit into
mainfrom
FXA-13911-passkey-sync-mobile

Conversation

@vpomerleau

@vpomerleau vpomerleau commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Because

  • On mobile Firefox (reproduced on iOS, reported on Android), signing in to Sync
    via a passkey did nothing — the browser was left in a "syncing paused" state
    with no redirect to the password fallback. This affected both standard
    (password) and passwordless accounts.
  • Mobile Firefox commonly omits the service=sync URL param and infers Sync from
    the client ID, so getService() returned undefined, the server never set
    requiresPasswordForSync, and the password step required to derive Sync keys
    was silently skipped.

This pull request

  • Derives the service from integration.isSync() ? 'sync' : integration.getService()
    in packages/fxa-settings/src/lib/passkeys/signin-flow.ts, so Sync sign-ins
    reliably trigger the password fallback redirect (/signin_passkey_fallback for
    standard accounts, /post_verify/set_password for passwordless). isSync() is
    the same signal already trusted for the can-link check.
  • Sets performNavigation: !integration.isFirefoxMobileClient() in
    packages/fxa-settings/src/pages/Signin/SigninPasskeyFallback/container.tsx so
    mobile lets Firefox complete Sync via WebChannel messages instead of navigating
    the WebView away — matching the existing idiom in SigninTokenCode,
    SigninTotpCode, SigninRecoveryCode, and SigninRecoveryPhone.
  • Adds regression tests covering service=sync when the URL param is absent, and
    mobile vs desktop navigation behaviour in the fallback container.

Issue that this pull request solves

Closes: FXA-13911

Checklist

Put an x in the boxes that apply

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).
  • I have manually reviewed all AI generated code.

How to review (Optional)

STR:

  • with Firefox iOS and/or Firefox for Android emulator and local fxa stack
    • create a Mozilla account
    • set up a passkey for the account
    • use the passkey to sign in to sync on Firefox iOS and/or Firefox for Android

Expectation:

  • prompted to enter account password after verifying passkey
  • signed into sync

Bug:

  • no password prompt
  • sync sign-in incomplete "syncing paused" with no recovery

Screenshots (Optional)

Please attach the screenshots of the changes made in case of change in user interface.

Other information (Optional)

Pre-merge review completed: /fxa-review returned APPROVE (0 blocking issues) and
/fxa-security-review found no security concerns. Client-side change in
fxa-settings; validation via Playwright Sync passkey functional tests.

… mobile

Because:
 - On mobile Firefox, signing in to Sync via a passkey left the browser in a
   "syncing paused" state with no redirect to the password fallback. Mobile
   commonly omits the service=sync URL param (defaulting to Sync via clientId),
   so getService() returned undefined and the server never set
   requiresPasswordForSync.

This commit:
 - Sends service=sync for Sync integrations using isSync() — the signal already
   trusted for the can-link check — instead of the often-absent service URL
   param, so the password fallback redirect fires for both standard and
   passwordless accounts.
 - Skips navigation on mobile in the passkey password fallback so Firefox drives
   Sync completion via WebChannel messages rather than navigating the WebView
   away.

Closes #FXA-13911

Copilot AI 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.

Pull request overview

This PR fixes a mobile Firefox Sync passkey sign-in regression where the flow could silently skip the required password fallback (leaving Sync “paused”) when service=sync was omitted from the URL. It makes the passkey completion call reliably identify Sync sign-ins and prevents WebView navigation on Firefox mobile so Sync completion can be driven via WebChannel.

Changes:

  • Force service: 'sync' when integration.isSync() is true (even if integration.getService() is undefined), ensuring the server sets requiresPasswordForSync.
  • Pass performNavigation: !integration.isFirefoxMobileClient() to handleNavigation in the passkey fallback password step to avoid navigating away on mobile Firefox.
  • Add regression tests for missing service param handling and desktop vs mobile navigation behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
packages/fxa-settings/src/pages/Signin/SigninPasskeyFallback/container.tsx Disables navigation on Firefox mobile during passkey password fallback completion.
packages/fxa-settings/src/pages/Signin/SigninPasskeyFallback/container.test.tsx Adds tests asserting performNavigation is true on desktop and false on mobile.
packages/fxa-settings/src/lib/passkeys/signin-flow.ts Derives service as 'sync' when integration.isSync() to trigger Sync password fallback reliably.
packages/fxa-settings/src/lib/passkeys/signin-flow.test.tsx Adds test verifying completePasskeyAuthentication receives { service: 'sync' } when getService() is absent.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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