Skip to content

auth: NIP-98 verifier upgrades did:nostr → WebID via verificationMethod lookup (#4 Phase 2A via CID) #399

Description

@melvincarvalho

Phase 2A of #4 ("Add did:nostr SSO and Schnorr (NIP-98) authentication"), redirected onto the CID-document substrate that #386 + #397 just landed.

Problem

Today's NIP-98 path (src/auth/nostr.js) authenticates a request as did:nostr:<pubkey>. WAC then operates on that DID-shaped identity — useful for direct-did:nostr-in-ACL, but it doesn't give the user their WebID as the authenticated identity, so writes to their own profile fail unless ACLs explicitly grant did:nostr:.

#4's original Phase 2A solved this with owl:sameAs linking in the profile + a dedicated SSO endpoint. With the verificationMethod / authentication infrastructure now in place (#386 + #397/#398), there's a smaller, more uniform alternative: the same K→W lookup the LWS-CID verifier already does.

Proposed change

Augment verifyNostrAuth so that, on a successful Schnorr verification:

  1. Compute the resource WebID (from the request's pod / WebID URL — same logic the WAC layer already uses).
  2. Fetch that WebID's profile.
  3. Look for a verificationMethod whose publicKeyMultibase decodes to the same Nostr pubkey we just verified, and whose VM id is referenced by authentication.
  4. If found → return the WebID as the authenticated identity (instead of did:nostr:).
  5. If not found → return did:nostr:<pubkey> as today (no behaviour regression).

Decode of the f-form Multikey is straightforward — strip f prefix, strip e701 multicodec, strip parity byte, take the remaining 32-byte x-only hex. The doctor's B.2 (already shipped) emits exactly this shape.

Acceptance

  • A WebID profile that declares a Nostr Multikey VM in authentication accepts NIP-98 requests as the WebID (not did:nostr:)
  • WAC writes to the user's own resources (e.g. their profile) succeed under NIP-98 with no extra ACL entries
  • Profiles WITHOUT a matching VM continue to authenticate as did:nostr:<pubkey> (no behaviour change for Add did:nostr SSO and Schnorr (NIP-98) authentication #4 Phase 1)
  • Profile fetch goes through the same SSRF guard / cache as the LWS-CID verifier
  • No regression in existing did:nostr ACL paths or in the existing DID-document resolver in did-nostr.js

Why this and not the original Phase 2A design

The original design was independent of CID: link via owl:sameAs, build a dedicated SSO endpoint. With CID v1 + LWS10-CID now load-bearing for keys-in-profiles, going through the same VM mechanism:

Out of scope

  • Phase 2B (Nostr-first registration with auto-pod-create) — orthogonal
  • Phase 3 (relay discovery / NIP-97) — orthogonal
  • The dedicated /idp/nostr-login endpoint — separate, can be layered on top later
  • The CCG f-form vs z-form Multikey debate — already settled at f-form per w3c-ccg/community#254; this issue assumes f-form

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestnostrNostr relay, did:nostr auth, NIP-related

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions