@@ -15,7 +15,8 @@ with the smallest possible UI surface — one big button.
15151 . User clicks ** Sign in**
16162 . ` window.nostr.getPublicKey() ` — signer extension hands us the pubkey
17173 . ` fetch <resolver>/.well-known/did/nostr/<pubkey>.json ` — DID document with ` alsoKnownAs `
18- 4 . Redirect to the WebID's pod root
18+ 4 . Redirect to the WebID's pod root with ` ?webid=did:nostr:<pubkey> `
19+ attached, so the pod's auth widget knows who just arrived
1920
2021** Failure path** — at every step, if something's not set up, the
2122page shows a precise diagnosis + the user's next concrete action
@@ -24,10 +25,12 @@ resolver, etc.). PoC philosophy: assume everything works; gracefully
2425degrade with guidance when it doesn't.
2526
2627** Trade-off** : the user lands at their pod * without* an
27- authenticated Solid-OIDC session. They can browse public content;
28- anything WAC-protected prompts for a real session via whatever app
29- needs it. For the "magic SSO landing" promise that's enough — the
30- full OIDC + DPoP session is on the v0.2 roadmap.
28+ authenticated session. They can browse public content; anything
29+ WAC-protected prompts for a real session via whatever app needs it.
30+ The ` ?webid= ` handoff is plain text for now — unsigned, unverified.
31+ For the "magic SSO landing" promise that's enough — the signed
32+ handoff (NIP-98) is 0.0.2 phase 2, and the full authenticated
33+ session is 0.0.7 on the roadmap.
3134
3235No username box. No IdP picker. No "what app are you logging in from?"
3336question. Click → resolve → arrive.
@@ -41,7 +44,7 @@ question. Click → resolve → arrive.
4144│ │ Sign in to Solid │ ← only UI │
4245│ └──────────────────────┘ │
4346└────────────────┬───────────────────────┘
44- │ Solid-OIDC redirect to configured IdP
47+ │ fetch /.well-known/did/nostr/<pubkey>.json
4548 ▼
4649┌────────────────────────────────────────┐
4750│ JSS resolver chain (already shipped) │
@@ -55,6 +58,7 @@ question. Click → resolve → arrive.
5558 ▼
5659┌────────────────────────────────────────┐
5760│ Redirect to pod root │
61+ │ + ?webid=did:nostr:<pubkey> │
5862└────────────────────────────────────────┘
5963```
6064
@@ -71,24 +75,31 @@ npx serve . # any port
7175python3 -m http.server 8080
7276```
7377
74- Or open ` index.html ` directly (CDN imports resolve over the network).
78+ (A server is required — ` login.js ` is an ES module, and browsers
79+ block module scripts on ` file:// ` URLs.)
7580
7681## Configuration
7782
78- URL params (also persisted to ` localStorage ` so post-redirect navigation
79- finds them):
83+ URL params:
8084
8185| Param | Default | Purpose |
8286| -------| ---------| ---------|
83- | ` idp ` | ` https://solid.social ` | OIDC issuer to authenticate against |
87+ | ` resolver ` | ` https://solid.social ` | Host serving ` /.well-known/did/nostr/<pubkey>.json ` |
8488| ` next ` | pod root derived from WebID | Where to land after sign-in |
8589
86- Example: a Solid app wants users to authenticate and come back —
90+ [ ` https://nostr.social ` ] ( https://nostr.social ) serves as the
91+ [ did-nostr.com] ( https://did-nostr.com ) source fallback when a key
92+ isn't linked at the default resolver.
93+
94+ Example: a Solid app wants users identified and sent back —
8795
8896```
89- https://sso.solid.social/?idp =https://solid .social&next=https://myapp.example/
97+ https://sso.solid.social/?resolver =https://nostr .social&next=https://myapp.example/
9098```
9199
100+ (Resolver memory in ` localStorage ` — so return visits skip straight
101+ to the right host — is 0.0.6 on the roadmap.)
102+
92103## Hosting
93104
94105Three sensible deployment targets:
@@ -101,10 +112,11 @@ Three sensible deployment targets:
101112
102113## Status
103114
104- ** 0.0.1 — proof of concept** . Demonstrates the one-button UX
105- end-to-end against ` solid.social ` as the resolver. Users registered
106- with solid.social land at their pod in one click. Resolution uses
107- the JSS resolver chain shipped in
115+ ** 0.0.2 phase 1 — identity handoff** . The one-button UX works
116+ end-to-end against ` solid.social ` as the resolver, and the redirect
117+ now carries ` ?webid=did:nostr:<pubkey> ` so the pod's auth widget can
118+ pick up the arriving identity (unsigned for now; phase 2 signs it
119+ with NIP-98). Resolution uses the JSS resolver chain shipped in
108120[ #408 ] ( https://github.com/JavaScriptSolidServer/JavaScriptSolidServer/pull/408 )
109121through
110122[ #418 ] ( https://github.com/JavaScriptSolidServer/JavaScriptSolidServer/pull/418 ) .
@@ -115,21 +127,26 @@ Following JSS's own 0.0.x versioning (small, frequent bumps, each
115127adding one capability).
116128
117129- ** 0.0.1** — One-button flow against a single hardcoded resolver. ✅
118- - ** 0.0.2** — Step-by-step coaching UI: checklist that ticks each
130+ - ** 0.0.2** — Identity handoff to the pod. Phase 1: append
131+ ` ?webid=did:nostr:<pubkey> ` to the redirect (plain text). ✅
132+ Phase 2: sign it (NIP-98 in the URL fragment) so the pod can
133+ verify the arriving identity.
134+ - ** 0.0.3** — Step-by-step coaching UI: checklist that ticks each
119135 step (extension detected, pubkey resolved, DID doc found, WebID
120136 extracted, redirect) instead of a one-shot status line.
121- - ** 0.0.3** — Multi-resolver fallback: try a configurable list of
122- resolvers in order before giving up.
123- - ** 0.0.4** — Direct Nostr-relay resolution. Sits on top of
137+ - ** 0.0.4** — Multi-resolver fallback: try a configurable list of
138+ resolvers in order (` solid.social ` , then ` nostr.social ` as the
139+ did-nostr.com source fallback) before giving up.
140+ - ** 0.0.5** — Direct Nostr-relay resolution. Sits on top of
124141 [ JSS #414 ] ( https://github.com/JavaScriptSolidServer/JavaScriptSolidServer/issues/414 ) .
125142 Removes the hardcoded-resolver dependency entirely.
126- - ** 0.0.5 ** — User-preferred resolver memory: first successful
143+ - ** 0.0.6 ** — User-preferred resolver memory: first successful
127144 resolution is cached in ` localStorage ` so subsequent visits skip
128145 straight to the right host.
129- - ** 0.0.6 ** — Authenticated session: optional NIP-98 → DPoP
146+ - ** 0.0.7 ** — Authenticated session: optional NIP-98 → DPoP
130147 exchange against the IdP, so the user lands at their pod
131148 already signed in (not just navigated there).
132- - ** 0.0.7 ** — Passkey-only fallback. Sign in without a Nostr
149+ - ** 0.0.8 ** — Passkey-only fallback. Sign in without a Nostr
133150 extension via WebAuthn.
134151
135152## Why a separate repo?
0 commit comments