Skip to content

Add FXIOS-16685 [FxA Pairflow] Verify pairing v2 against a local FxA stack Part 2 - #35509

Open
vbudhram wants to merge 2 commits into
mozilla-mobile:mainfrom
vbudhram:fxa-pair-ios-v2-e2e
Open

Add FXIOS-16685 [FxA Pairflow] Verify pairing v2 against a local FxA stack Part 2#35509
vbudhram wants to merge 2 commits into
mozilla-mobile:mainfrom
vbudhram:fxa-pair-ios-v2-e2e

Conversation

@vbudhram

@vbudhram vbudhram commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📜 Tickets

Jira ticket
Github issue

💡 Description

Part 2 of FXIOS-16685, following #35460. Part 1 shipped pairing v2 itself. This PR makes it verifiable end to end against a local FxA stack, and adds the UI test that drives the whole flow.

Why the parser changes are here

FxAPairingURLParser allowed only accounts.firefox.com and accounts.stage.mozaws.net, over https. The functional test pairs against a local FxA stack at http://localhost:3030, which that allowlist rejects, so the deep link opened as an ordinary tab and never reached the pairing modal.

The parser now resolves the allowed origin from the content server the build is configured against. On a release build this is tighter than before: stage no longer routes unless the stage pref is set. Cleartext is confined to a loopback host, so a custom content server pointed at a remote http:// origin still cannot make a plaintext pairing link valid.

Two consequences follow from that:

Origin shape. The parser emits a lowercased scheme and host and drops a port that equals the scheme default. The WebChannel bridge compares baseURL against WKSecurityOrigin, which reports a lowercased host and port 0 for a default port. Without this, a link carrying :443 passes the parser and then has every WebChannel message dropped, so the page falls back to pairingVersion: 1 and renders the unsupported card after about three seconds.

China. createAccountManager selects FxAConfig.Server.china, which app-services maps to its own host (FxAccountConfig.swift maps .china to the distinct FxaServer.china). contentServerString has to select it too, or a genuine accounts.firefox.com.cn pairing link is treated as an untrusted URL while an accounts.firefox.com link is trusted and handed OAuth parameters minted against a different server.

RouteTests.testPairingRouteFromSystemCameraDeepLink moves from the stage host to the release host for the same reason: stage is no longer a trusted origin on an unconfigured build.

Note for reviewers: please do not restore the SyncIntegrationTestPlan skips

SyncIntegrationTestPlan.xctestplan deliberately no longer skips PairingTests.

The functional test builds the .xctestrun from that plan, then runs it with -only-testing:XCUITests/PairingTests/testPairingV2. A plan skip becomes a SkipTestIdentifiers entry in the .xctestrun, and -only-testing cannot override it. Restoring those three lines makes the run execute zero tests and still exit 0, which reads as a passing end-to-end test.

PairingTests.setUp throws XCTSkip without PAIRING_URL and CUSTOM_FXA_SERVER, so ordinary CI runs of that plan cost nothing. testPairingV2 is added to the skip lists of the four plans that skip the pairing class.

🎥 Demos

No new native UI. testPairingV2 attaches simulator screenshots of the supplicant card and the closed modal on failure.

📝 Checklist

  • I filled in the ticket numbers and a description of my work
  • I updated the PR name to follow our PR naming guidelines
  • I ensured unit tests pass and wrote tests for new code
  • If working on UI, I checked and implemented accessibility (Dynamic Text and VoiceOver) — n/a, no new native UI
  • If adding telemetry, I read the data stewardship requirements and will request a data review — n/a, no telemetry added
  • If adding or modifying strings, I read the guidelines and will request a string review from l10n — n/a, no strings added or modified
  • If needed, I updated documentation and added comments to complex code

…stack

The pairing URL parser accepted only the production and stage hosts over
https, so a local FxA stack could never route a pairing link. Resolve the
allowed origin from the content server the build is configured against, which
lets the functional test pair against its own stack and keeps a stray host
out. Confine cleartext to a loopback host, so a custom content server on a
remote http origin still cannot make a plaintext link valid.

Emit the URL in the shape the WebChannel bridge expects: a lowercased scheme
and host, and no port when it is the scheme default. The bridge compares
against WKSecurityOrigin, which reports port 0 for a default port, so a link
with :443 would otherwise pass the parser and then lose every message.

Select the China content server when the China sync pref is set, in the same
order createAccountManager uses. The account manager selects
FxAConfig.Server.china, which maps to its own host.

Add testPairingV2, which the pairingFlowV2iOS.spec.ts functional test drives
against a real authority and a live stack. SyncIntegrationTestPlan must not
skip PairingTests: that plan builds the xctestrun the functional test runs
with -only-testing, and a skip there becomes a SkipTestIdentifiers entry that
-only-testing cannot override, so the run would execute no tests and pass.
The parser now matches the content server the build is configured against, so
the stage host no longer routes on a release build. Use the release host,
which is what an unconfigured test build resolves to.
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