Skip to content

WhatsApp phone-number linking on passkey-protected accounts (companion WebAuthn) #79

Description

@MaxGhenis

Split out from #77 / PR #78, which shipped phone-number pairing but hit this on a real account.

What happens

On an account with a WhatsApp passkey, code linking gets all the way through registration — the phone accepts the typed code and companion_finish returns ok — and then the server sends passkey_prologue_request with a WebAuthn challenge (rpId whatsapp.com, 10-minute timeout). The companion must answer with a real WebAuthn assertion. We can't produce one: the passkey lives in the user's phone/keychain, and platform WebAuthn APIs (rightly) won't let a third-party app assert for someone else's rpId. The bridge now surfaces this clearly ("account is protected by a passkey — scan the QR code instead") instead of idling silently.

whatsmeow gained the protocol plumbing on 2026-06-30 (pair: add support for passkeys: events.PairPasskeyRequest, SendPasskeyResponse, SendPasskeyConfirmation) — we're on that version. What's missing is the authenticator side.

Options to investigate

  1. Native macOS ceremony via the Swift app — AuthenticationServices can do cross-site passkey assertions only for associated domains; whatsapp.com won't associate us. Likely dead end, but worth confirming whether the hybrid (phone-scan QR / CTAP2 hybrid transport) flow is reachable from a non-associated app.
  2. Hand off to the browser — open a local page that runs navigator.credentials.get with the challenge... same rpId restriction applies (page origin must match rpId). Dead end unless WhatsApp's own web flow can be leveraged.
  3. Track upstream — watch how mautrix-whatsapp / Beeper wire PairPasskeyRequest in practice; if they find a supported handoff (e.g. the pairing_handoff_proof path pushing the ceremony to the primary phone), mirror it.
  4. Documented workaround (current state): QR linking is unaffected by the passkey step; failing that, temporarily remove the passkey (WhatsApp → Settings → Account → Passkeys), link, re-add.

Until resolved, the UI error message + runbook guidance are the mitigation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions