fix(desktop): offer passkeys on Microsoft sign-in in the preview browser#30047

closed2
main
fix/issue-30014
opened7d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 7d ago

Problem

Microsoft sign-in (Entra and Microsoft accounts) in the desktop preview browser does not offer passkeys. Microsoft decides this from the User-Agent request header: when it contains Electron/<version>, the server leaves passkeys out of the sign-in page config ($Config.fIsFidoSupported), so "Face, fingerprint, PIN or security key" never appears. On main (cefb544af3), opening the Entra authorize page in a preview tab and clicking "Sign-in options" shows only GitHub and "Sign in to an organization".

Change

Each preview session now registers a webRequest.onBeforeSendHeaders listener for login.microsoftonline.com, login.microsoft.com and login.live.com. It removes only the Electron/<version> token from the outgoing User-Agent header. The session User-Agent and navigator.userAgent stay native, and every other host still gets the native header. A rewritten session User-Agent breaks Cloudflare Turnstile (see the existing "keeps the guest's effective User-Agent equal to Electron's native one" test).

Scope and approval

Fixes pingdotgg/t3code#30014

Verification

  • vp test run apps/desktop/src/preview/BrowserSession.test.ts: 9/9 pass. The new test, "drops only the Electron/ token from the User-Agent sent to Microsoft sign-in", fails on main:
    1AssertionError: preview sessions send the Electron/ token to Microsoft sign-in (https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=x&response_type=code)
    2Expected: "… T3CodeDev/44.10.0 Chrome/152.0.7977.169 Safari/537.36"
    3Received: "… T3CodeDev/44.10.0 Chrome/152.0.7977.169 Electron/44.10.0 Safari/537.36"
    In the same test, a challenges.cloudflare.com request keeps the native header.
  • Real desktop app, Linux, Electron 44.10.0 / Chromium 152, under Xvfb. Before = cefb544af3, after = 773c709d4a, each run from its own checkout with a fresh database and no account. A preview tab opened the Entra authorize page (public Office client id) and "Sign-in options". The User-Agent that was actually sent was read with a session.webRequest.onSendHeaders observer; nothing was added to the fix's listener.
BuildHostSent User-Agent ends withnavigator.userAgentEntra/Live FIDO flagPasskey option in Sign-in options
before cefb544af3login.microsoftonline.comChrome/152.0.7977.169 Electron/44.10.0 Safari/537.36native$Config.fIsFidoSupported absentabsent
after 773c709d4alogin.microsoftonline.comChrome/152.0.7977.169 Safari/537.36native (unchanged)$Config.fIsFidoSupported: true"Face, fingerprint, PIN or security key — Use your device to sign in with a passkey"
before / afterlogin.live.comwith / without Electron/44.10.0nativeServerData.fIsFidoSupported false → truenot checked
before / afterlogin.microsoft.com (302 → office.com → login.microsoftonline.com)with / without Electron/44.10.0nativen/an/a
before / afterdemo.turnstile.workers.dev and the challenges.cloudflare.com framenative on both builds, byte-identicalnativen/athe Turnstile widget succeeds on both builds

On login.live.com, Microsoft serves a different sign-in layout from request to request (sClientRingId R1/R2/R3 changes across repeated fetches with the same User-Agent). Only fIsFidoSupported follows the Electron/ token. Without the token, the response matches what a plain Chrome User-Agent gets (fIsFidoSupported: true, three fetches each).

Visible difference on Entra's Sign-in options card (Linux): the passkey row is added, the card grows 72 px and re-centres, and initial focus moves to the new first row. Nothing else in the T3 window changes.

Before/after stills, zero-threshold and 2% diff images, and interaction recordings were captured but are not embedded in this body.

Not verified:

  • cannot-verify windows: the reporter's Windows 11 flow with Windows Hello / 1Password and an enrolled work account. No full passkey sign-in was completed; the Linux run proves only that Microsoft now offers passkeys.
  • cannot-verify macos, and Windows again: once the token is gone, the Entra authorize URL with a Windows or macOS User-Agent returns Microsoft's "Redirecting" single-sign-on check page (BssoInterrupt, overallTimeoutMs: 4000) before the sign-in form, just as Chrome on those platforms does. With the token it returns the sign-in form directly. Linux gets the form directly either way. Seen with curl only; how long this hop takes inside the Electron preview has not been measured.
  • Turnstile with a production site key. The demo uses Cloudflare's always-pass test key. The header Cloudflare receives is byte-identical before and after, which is what the Turnstile constraint depends on.
  • Regional and government Microsoft sign-in hosts (login.microsoftonline.us, login.partner.microsoftonline.cn, *.b2clogin.com) are not covered by this change.

Triaged, fixed and verified by Claude Opus 5.5 (Claude Code harness) as lead, with Claude Opus 5.5 and GPT-6.1-sol (Codex) step agents.

🤖 Generated with Claude Code

Checks

25 successful · 12 skipped · 1 neutral
All checks passed
773c709

Added 2 commits

  • fix(desktop): offer passkeys on Microsoft sign-in in the preview browser773c709
  • test(desktop): reproduce #30014, Electron/ UA token reaches Microsoft sign-inf48d406
Synced from GitHub

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — The preview browser will automatically omit Electron identification on three Microsoft sign-in hosts so passkeys become available, while other hosts remain unchanged. A human must confirm the change to the default Microsoft sign-in experience.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

BrowserSession now removes the Electron token from outgoing User-Agent headers for three Microsoft sign-in hosts. Tests cover the matching URLs, an unrelated Cloudflare URL, and the request-header callback.

Changes: Microsoft sign-in User-Agent handling

Layer / File(s)Summary
Register and validate the Microsoft sign-in header rewrite
apps/desktop/src/preview/BrowserSession.ts, apps/desktop/src/preview/BrowserSession.test.ts
BrowserSession registers a before-send-headers handler for Microsoft sign-in URLs. The handler removes the Electron token from a present User-Agent header and forwards other headers unchanged. Tests cover the registration and header behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

  • pingdotgg/t3code#30018: Addresses the same Entra passkey issue with the same site-specific Electron token removal.
  • pingdotgg/t3code#26771: Uses the same BrowserSession pattern to remove the Electron token for a specific site.

Suggested labels: bugfix, size:S, vouch:unvouched

Suggested reviewers: maria-rcks, macroscopeapp

Merge Risk: External image Minimal · up to 773c7

The change targets Microsoft sign-in headers. No merge-blocking issue was established.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely identifies the desktop preview browser fix that enables passkeys on Microsoft sign-in.
Linked Issues checkPassedDirectly linked issue #30014 requires three things: (1) remove only the Electron/<version> token from the User-Agent request header for login.microsoftonline.com, login.microsoft.com and login.live…
Out of Scope Changes checkPassedThe whole-PR change set (base cefb544af3 to head 773c709d4a) has two parts. The BrowserSession.ts change adds the URL-filtered header listener and its constants, which are the issue's requested scope.…
Description checkPassedThe description follows the required structure and clearly explains the problem, change, scope, tests, manual verification, observed results, and unverified cases. It links issue #30014 and provides d…
Full details: Linked Issues check

Explanation

Directly linked issue #30014 requires three things: (1) remove only the Electron/&lt;version&gt; token from the User-Agent request header for login.microsoftonline.com, login.microsoft.com and login.live.com; (2) leave navigator.userAgent and other sites unchanged; (3) let Entra offer the passkey option in the preview browser. The reviewed head adds a webRequest.onBeforeSendHeaders listener in apps/desktop/src/preview/BrowserSession.ts (inside getSession, where the session is created). It applies only to MICROSOFT_SIGN_IN_URLS (the three hosts, /* paths) and replaces ELECTRON_USER_AGENT_TOKEN (/ Electron/[^ ]+/) with an empty string in requestHeaders["User-Agent"]. No navigator.userAgent or session user-agent code changes. The base file has no prior onBeforeSendHeaders listener, so the new listener does not replace an existing one. The test file adds "drops only the Electron/ token from the User-Agent sent to Microsoft sign-in", which covers the Microsoft URLs and a challenges.cloudflare.com request that keeps the native header. The PR reports a Linux run on Electron 44.10.0 where the sent header lacks the Electron token and Entra shows the passkey option; the reported before/after table supports this. Not verified: a Windows 11 passkey sign-in, which the issue reported. The regional Microsoft hosts are not covered, and the issue does not require them.

Full details: Out of Scope Changes check

Explanation

The whole-PR change set (base cefb544af3 to head 773c709d4a) has two parts. The BrowserSession.ts change adds the URL-filtered header listener and its constants, which are the issue's requested scope. The BrowserSession.test.ts change adds the mocked listener hook and the test for the Microsoft and Turnstile URLs, which supports that behavior. The PR body describes no other code changes. The change does not alter the session User-Agent, navigator.userAgent, the permission handlers, or any other host. No change is unrelated to #30014.

Full details: Description check

Explanation

The description follows the required structure and clearly explains the problem, change, scope, tests, manual verification, observed results, and unverified cases. It links issue #30014 and provides detailed evidence. Screenshots and recordings are mentioned but not embedded, and explicit maintainer approval is not shown, but the description is otherwise complete.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
External image Recent review info
External image Run configuration
External image Commits

Reviewing files that changed from the base of the PR and between cefb544af3c98224874419198c0359b652ca3c94 and 773c709d4a0281a226959b95e2e0dd7b8684a604.

External image Files selected for processing: 2
  • apps/desktop/src/preview/BrowserSession.test.ts
  • apps/desktop/src/preview/BrowserSession.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.

Closing as a duplicate of pingdotgg/t3code#30018, which makes the same host-scoped change and was opened first.

The verification here applies to that PR too. On Linux at 773c709d (Electron 44.10.0), the sent User-Agent loses only Electron/44.10.0 for the three Microsoft hosts, Entra's fIsFidoSupported goes from absent to true, and Sign-in options shows "Face, fingerprint, PIN or security key". With a Windows or macOS User-Agent and no token, Entra's authorize URL first returns its "Redirecting" single-sign-on check page (BssoInterrupt, overallTimeoutMs: 4000); with the token it returns the sign-in form directly. How long that hop takes inside Electron is unmeasured.