| [ Web Proxy ] |
| Viewing: https://javascriptsolidserver.github.io/JavaScriptSolidServer/docs/lws.html | [Back] [Original] |
JSS is aligned end-to-end with the W3C Linked Web Storage 1.0 Authentication Suite (FPWDs published 2026-04-23) and its substrate, W3C Controlled Identifiers v1.0 pod profiles are CID-shaped, users add keys via the doctor, and the server accepts strict LWS10-CID JWTs as an HTTP auth method alongside the existing Solid-OIDC and NIP-98 paths.
Convergence tracker: #386. FPWD-alignment audit: #319.
| What it means | Status | |
|---|---|---|
| 1. Profile shape | A WebID profile thats structurally a W3C Controlled Identifier document right @context, right vocabulary, parseable as a CID document by any LWS-aware tool |
Yes (since v0.0.174, #388) |
| 2. Profile carries keys | The CID document actually declares verificationMethod entries an LWS verifier can look up by kid |
Browser-side via the doctor B.2 for Nostr/Multikey, B.3 for ES256K/JsonWebKey. The doctor authenticates as the WebID owner via Solid-OIDC and PATCHes the VM into the profile. |
| 3. Server accepts LWS-CID JWTs | An incoming request with an LWS-CID self-signed JWT (sub/iss/client_id triple-equality, kid lookup against the WebIDs verificationMethod, signature check) |
Shipped in v0.0.177 (#398). Strict FPWD 4 ES256K is the focus algorithm; ES256, ES384, EdDSA, RS256 also accepted. |
| Bonus: NIP-98 WebID | A Schnorr-signed NIP-98 request authenticates as the WebID (not did:nostr:) when the pubkey is declared as a CID verificationMethod referenced from authentication |
Shipped in v0.0.178 (#400). No client-side change the doctors B.2 output is enough to light it up. |
src/webid/profile.js declares the six CID v1 vocabulary terms controller, verificationMethod, authentication, assertionMethod, publicKeyJwk, publicKeyMultibase in the profiles @context (inline, so JSSs JSON-LD Turtle conneg layer can expand them without fetching external contexts), and emits a controller triple pointing at the WebID itself per CID v1s self-control contract.
A freshly-created pods profile/card.jsonld looks like this (excerpt the existing Solid predicates oidcIssuer, pim:storage, ldp:inbox, service etc. are unchanged):
{
"@context": {
"foaf": "...", "solid": "...", "cid": "https://www.w3.org/ns/cid/v1#", "lws": "https://www.w3.org/ns/lws#",
"controller": { "@id": "cid:controller", "@type": "@id" },
"verificationMethod": { "@id": "cid:verificationMethod", "@container": "@set" },
"authentication": { "@id": "cid:authentication", "@type": "@id", "@container": "@set" },
"assertionMethod": { "@id": "cid:assertionMethod", "@type": "@id", "@container": "@set" },
"publicKeyJwk": { "@id": "cid:publicKeyJwk", "@type": "@json" },
"publicKeyMultibase": { "@id": "cid:publicKeyMultibase" }
},
"@id": "https://alice.example/profile/card.jsonld#me",
"@type": ["foaf:Person"],
"controller": "https://alice.example/profile/card.jsonld#me"
// verificationMethod / authentication / assertionMethod arrays are
// intentionally absent until Phase B's doctor app PATCHes them in.
}
The doctor is a separate browser-side tool that signs in to your pod via Solid-OIDC and writes verificationMethod entries to your profile. After the round-trip your profile has:
"verificationMethod": [
{ "id": "...#nostr-key-1", "type": "Multikey", "controller": "...#me",
"publicKeyMultibase": "fe70102" },
{ "id": "...#lws-key-1", "type": "JsonWebKey", "controller": "...#me",
"publicKeyJwk": { "kty": "EC", "crv": "secp256k1", "alg": "ES256K", "x": "", "y": "" } }
],
"authentication": ["...#nostr-key-1", "...#lws-key-1"]
The Multikey entry handles did:nostr binding + NIP-98 lookup; the JsonWebKey entry handles strict LWS10-CID JWT auth. Both can be the same secp256k1 key different signature schemes (Schnorr vs ECDSA), same private key.
Because Phase A already declared the context terms, this is a pure data-layer PATCH no @context rewrite needed.
src/auth/lws-cid.js)When an incoming request carries an LWS-CID JWT (detected by an Authorization: Bearer <jwt> whose JWT-header kid is an http(s) URL with a fragment), JSS:
sub === iss === client_id (canonicalized via URL parsing) that URI is the WebID being claimedaud includes the server origin, exp not past, iat recent, lifetime 1 hour@id equals the JWTs sub (closes a profile-substitution attack)kid in verificationMethod; the entry must be referenced from authentication and its controller must match the profiles outer controller@noble/curves (already in tree from NIP-98); ES256, ES384, EdDSA, RS256 via joseThe verifier joins the existing auth methods (Solid-OIDC, NIP-98, Bearer-JWT-from-IDP, WebID-TLS) preference order is OIDC LWS-CID NIP-98 Bearer fallback (per #306).
src/auth/nostr.js)Built on top of the LWS-CID infrastructure (#400): when a NIP-98 requests signing pubkey is declared as a CID verificationMethod (and the VM is in authentication) on the resource owners WebID profile, the request authenticates as the WebID instead of did:nostr:<pubkey>. Match is by f-form Multikey or by JsonWebKey full-point (x AND y, BIP-340 even-y). Profile fetch uses the same SSRF guard / cache as the LWS-CID verifier. No client-side change Nostr clients sign as today.
So: anyone whos used the doctors B.2 to add a Nostr Multikey VM gets WebID-based NIP-98 sign-in for free.
docs/authentication.md full JSS auth surface (OIDC, NIP-98, LWS-CID, passkey, etc.)docs/nostr.md Nostr relay + did:nostr resolution@context array form support (turtle conneg)@type:'@json' literal handling (turtle conneg)| Web Proxy Viewer | New URL | Original Page |