Legacy /pair pairing fallback cannot pass NIP-42 — desktop signs the URL with path, relay expects bare origin

Open Beginner friendly
#4,932 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
rust

Research direction

Start in desktop/src-tauri/src/commands/pairing.rs at resolve_pairing_relay_url and handle_nip42_auth, then compare the expected value in crates/buzz-relay/src/api/bridge.rs and normalization in crates/buzz-auth/src/nip42.rs. Reproduce legacy /pair pairing against relay-v0.2.0 and verify that NIP-42 authentication succeeds without the relay URL mismatch.

Written by the indexing model from the issue text.

Description

Summary

On relays whose NIP-11 lacks pairing_relay_url (which includes both tagged relay releases, relay-v0.1.1 and relay-v0.2.0), Buzz Desktop's device pairing falls back to the legacy convention wss://<relay-host>/pair — and then cannot authenticate, because the desktop signs its NIP-42 AUTH event with that URL including the path, while the relay expects the bare origin. The mismatch is unconditional, so legacy-path pairing fails for every operator on the tagged releases.

The two sides of the contract

Desktop (desktop/src-tauri/src/commands/pairing.rs): when NIP-11 has no pairing_relay_url but advertises NIP-43, resolve_pairing_relay_url builds <main relay>/pair (PairingRelay::LegacyPath), and handle_nip42_auth signs the AUTH event with that full URL:

let relay_url_parsed = nostr::RelayUrl::parse(relay_url)...;   // wss://<host>/pair
... s.sign_event(nostr::EventBuilder::auth(challenge, relay_url_parsed))

Relay (crates/buzz-relay/src/api/bridge.rs, nip42_expected_relay_url): the expected value is derived from the tenant host, explicitly pathless — the comment states the contract the desktop is violating:

/// Path is empty — clients put the bare WS origin (`ws://host[:port]`) in the
/// `relay` tag, matching how `EventBuilder::auth` accepts a [`nostr::RelayUrl`].
format!("{scheme}://{}", tenant.host())

normalize_relay_url in crates/buzz-auth/src/nip42.rs preserves paths (it only trims a trailing slash), so wss://<host>/pair vs wss://<host> never match. Since every WS connection must complete NIP-42 within the fixed 5s window, the connection is then closed.

Observed behaviour

Desktop v0.5.4 against relay-v0.2.0, with an open pairing relay served behind a path-stripping proxy at <relay-host>/pair (so the transport itself works — the WS upgrade succeeds and the QR renders briefly):

Relay log, every attempt:

WARN NIP-42 auth failed  error="relay url mismatch"
WARN NIP-42 auth timeout — closing connection  timeout_secs=5
INFO WebSocket connection closed

Desktop surfaces this as relay closed waiting for EOSE a few seconds after the QR appears.

Suggested fix (either side resolves it)

  • Desktop: sign the bare origin of the pairing URL in the AUTH event — strip the path from relay_url before EventBuilder::auth in handle_nip42_auth. One line, and it matches the relay's documented expectation.
  • Or relay: make nip42_expected_relay_url (or the comparison) tolerant of the client's connect path.

Operator workaround meanwhile

Run a relay recent enough to support BUZZ_PAIRING_RELAY_URL, and advertise the open pairing relay at a dedicated hostname (path /). The desktop then takes the PairingRelay::Configured route, dials a pathless URL, signs the bare origin, and auth succeeds. Verified working end-to-end; only the legacy path convention is broken.

Happy to provide fuller logs or test against a patched build.

Dominant language
Rust
Stars
33.7k
Forks
4.4k
Avg merge
1d 21h
Merged PRs (30d)
239

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from block/buzz

All issues in block/buzz

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.