[Bug] Onboarding fails with "Nostr identity challenge is invalid" when the system clock is behind - error gives no indication of clock skew
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
**Describe the bug**
During first-run onboarding, after completing email verification, the "Finish connecting Buzz" dialog fails when clicking **Connect and continue**:
> Nostr identity challenge is invalid. Correlation ID: [redacted]
The message gives no indication of the cause and no recovery path — retrying fails identically, and the only other action available is to dismiss the dialog, which leaves onboarding incomplete.
**Root cause**
The machine's clock was **164 seconds behind** true time. Verified against four independent references:
| Reference | Measured offset |
|---|---|
| `w32tm /stripchart` vs `time.windows.com` | `+164.51 s` |
| HTTP `Date` header, cloudflare.com | `-164.04 s` |
| HTTP `Date` header, google.com | `-163.81 s` |
| HTTP `Date` header, github.com | `-154.70 s` |
Two details made this genuinely hard to spot:
1. The machine is domain-joined, and was in sync **with its domain time source to within 0.02 s**. Windows reported time synchronisation as healthy and "Set time automatically" was enabled. It was the domain's own upstream clock that was wrong — so from the user's point of view, everything about the local clock looks correct and well-managed.
2. Nothing in the Buzz error mentions time.
The client builds the identity-binding Nostr event with a `created_at` taken from the local clock (`build_nostr_identity_binding_event` in `desktop/src-tauri/src/builderlab.rs`). With the clock ~2.7 minutes slow, the signed event carries a timestamp *earlier than the moment the server issued the challenge*, and verification at `/v1/buzz/nostr-identities/verify` rejects it.
**Expected behavior**
Detect and surface clock skew instead of reporting a generic invalid-challenge error. For example:
> Your computer's clock is 164 seconds behind. Buzz signs your identity with a timestamp, so setup cannot complete until the clock is corrected.
This requires no extra round trip:
- the challenge response already returns `expires_at`
- the HTTP response to the challenge call carries a `Date` header
Either can be compared against the local clock before signing. The check is cheap enough to run pre-emptively rather than only on failure.
**To reproduce**
1. Set the system clock approximately 3 minutes behind true time
2. Launch Buzz as a new user and complete email verification
3. On the "Finish connecting Buzz" dialog, click **Connect and continue**
4. Observe the error
**Environment**
- Buzz 0.4.26 (`Buzz_0.4.26_x64-setup_alpha-unsigned.exe`)
- Windows 11 Pro x64, build 26200
- Standard (non-administrator) domain-joined user
Worth noting for the severity assessment: a standard user in this situation **cannot correct the clock themselves**. `w32tm /resync` returns `Access is denied. (0x80070005)`, the user token does not hold `SeSystemtimePrivilege`, and a manual "Sync now" would simply re-inherit the same incorrect upstream time. Onboarding is a hard block until an administrator fixes the upstream time source — which is a plausible situation on any managed corporate machine.
**Related**
Searched open and closed issues for "identity challenge" and for "nostr challenge invalid" — no existing report found. Other onboarding-blocker reports sharing the same "no recovery path" shape: #2484, #2399, #2498.
Contributor guide
Research direction
Start in desktop/src-tauri/src/builderlab.rs at build_nostr_identity_binding_event and trace the onboarding challenge response through /v1/buzz/nostr-identities/verify. Compare the local clock with expires_at or the response Date header before signing, then verify that a clock-skew explanation and recovery path are shown instead of the generic invalid-challenge error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- authentication, desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100