Skip to content

feat(nwcp): add NIP-42 client AUTH support#38

Open
satwise wants to merge 2 commits into
lnbits:mainfrom
satwise:feat/nip42-client-auth
Open

feat(nwcp): add NIP-42 client AUTH support#38
satwise wants to merge 2 commits into
lnbits:mainfrom
satwise:feat/nip42-client-auth

Conversation

@satwise

@satwise satwise commented May 3, 2026

Copy link
Copy Markdown

Problem

When a NIP-42-enabled relay sends ["AUTH", "<challenge>"], nwcprovider hits the catch-all raise Exception("Unknown message type") branch. The error is logged and no response is sent. The relay closes subscriptions because the challenge is never answered.

This makes nwcprovider completely incompatible with any relay that has nip42_auth = true.

When a NIP-42-enabled relay sends [AUTH, challenge], nwcprovider now
responds with a signed kind-22242 event (relay URL + challenge tags).

Previously the AUTH message type hit the catch-all raise Exception branch,
causing an error log and no response. The relay then closed subscriptions
because the challenge was never answered.

Fix: add _on_auth_message handler and route msg[0]=AUTH to it in
_on_message.

Closes: (to be linked after PR filed)
Ref: https://github.com/nostr-protocol/nips/blob/master/42.md

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds NIP-42 client-side AUTH challenge handling to NWCServiceProvider so the provider can interoperate with relays that require ["AUTH", "<challenge>"] responses instead of failing with an “Unknown message type” exception.

Changes:

  • Route incoming relay "AUTH" messages to a dedicated handler.
  • Implement _on_auth_message to build/sign a kind 22242 auth event and send it back via ["AUTH", event].

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread nwcp.py
Comment on lines 515 to 516
except Exception as e:
logger.error("Error parsing event: " + str(e))
Comment thread nwcp.py
Comment on lines +530 to +539
auth_event: dict = {
"kind": 22242,
"content": "",
"created_at": int(time.time()),
"tags": [
["relay", self.relay],
["challenge", challenge],
],
}
self._sign_event(auth_event)
@satwise satwise mentioned this pull request May 3, 2026
@satwise

satwise commented May 4, 2026

Copy link
Copy Markdown
Author

Dependency note — this PR is a blocker for newly-exposed NIPs on our Umbrel relay fork.

satwise/nostr-rs-relay (fork of scsibug/nostr-rs-relay) now advertises and partially enforces NIP-17 (private DMs), NIP-50 (full-text search), and NIP-59 (gift wrap) — all gated behind nip42_auth = true on the relay side. Full activation path:

  1. ✅ This PR (nwcprovider#38) — NWC client answers ["AUTH", challenge] so nwcprovider can authenticate against a NIP-42 relay
  2. nostrrelay#44 — server routes ["AUTH", signed_event] through _handle_event so auth pubkey is actually set
  • Finally closes LNBits platform GAP between NostrRelay & NWCprovider Extensions to monetize AI Agent subscriptions
  1. Then: flip nip42_auth = true in config.toml on relay
  2. Then: NIP-50 full-text search and NIP-17/59 delivery restrictions become fully operational

NIP-11 on wss://nostr.janx.com currently advertises NIPs [1,2,9,11,12,15,16,20,22,33,40,44,50,77]. NIP-17/42/59 are added to the advertisement once auth is enabled. All infrastructure is ready — so only this LNbits PR is the only remaining blocker to test a fully NIP enabled nostr-rs-relay-v0.9.1 as an LNbits user. Successful testing also offers an alternative to if the load gets too much for LNbits NostrRelay, which happened in my case.

Thank you for your kinds consideration.

@DoktorShift

Copy link
Copy Markdown

@satwise Thanks for this- clean fix, and it lines up nicely with the existing resubscribe logic so the auth-then-resubscribe flow should just work. Verified it against NIP-42 too: kind 22242, relay/challenge tags, and empty content all check ot 👍

Couple of small things:

  • When the relay rejects auth with ["OK", id, false, ...], right now we silently pass. Could we add a debug/warning log there? Makes diagnosing failures, for example a relay canonicalizing the URL differently than self.relay, way easier.
  • Any chance of a quick unit test for _on_auth_message? Something asserting it emits a valid signed 22242 with the right tags. Since this is hard to verify without a live NIP-42 relay, a test would give us confidence and guard that branch going forward.

Neither is a blocker on the logic, happy to merge either way, just nice-to-haves. 🙏

Implement stakeholder-requested relay auth/publish diagnostics.

Changes:

- Route incoming OK frames to _on_ok_message instead of ignoring them.

- Log rejected OK responses at warning level with relay, event id, and relay reason.

- Log accepted OK responses and malformed OK payloads at debug level.

Validation summary (no package unit test added, per request):

- Ad-hoc runtime validation confirmed AUTH response emits kind 22242 with relay/challenge tags and valid signature.

- Log checks confirmed expected rejected/accepted/malformed OK diagnostics are emitted.
@satwise

satwise commented Jun 3, 2026

Copy link
Copy Markdown
Author

@satwise Thanks for this- clean fix, and it lines up nicely with the existing resubscribe logic so the auth-then-resubscribe flow should just work. Verified it against NIP-42 too: kind 22242, relay/challenge tags, and empty content all check ot 👍

Couple of small things:

  • When the relay rejects auth with ["OK", id, false, ...], right now we silently pass. Could we add a debug/warning log there? Makes diagnosing failures, for example a relay canonicalizing the URL differently than self.relay, way easier.
  • Any chance of a quick unit test for _on_auth_message? Something asserting it emits a valid signed 22242 with the right tags. Since this is hard to verify without a live NIP-42 relay, a test would give us confidence and guard that branch going forward.

Neither is a blocker on the logic, happy to merge either way, just nice-to-haves. 🙏

@DoktorShift thank you for your review and suggestions. I am happy to accommodate your requests. I implemented relay OK response handling so rejected publish/auth outcomes are now surfaced as warning logs with relay, event id, and reason, while accepted and malformed OK responses are captured at debug level for diagnostics.
Commit link: satwise@9c4543f

Included are the results of the unit-test validation you requested for the AUTH path:
auth_cmd: true
kind_22242: true
has_relay_tag: true
has_challenge_tag: true
signature_valid: true

Pertinent log results:

  • Relay wss://relay.example rejected event c1341902617ee50da3986ba71da490074e44f63d982db47958882e83c32dd84a: auth-required: challenge failed
  • Relay wss://relay.example accepted event c1341902617ee50da3986ba71da490074e44f63d982db47958882e83c32dd84a: stored
  • Received malformed OK message from relay wss://relay.example: ['OK']

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.

4 participants