Skip to content

Align WebID profile emission with LWS 1.0 (dual-write CID service[]) #320

@melvincarvalho

Description

@melvincarvalho

Part of #319 (LWS 1.0 Auth Suite alignment). Scoped as a small, low-risk first step.

Why

The LWS 1.0 OpenID Connect FPWD specifies that a verifier looks up trust via a service object in the user's Controlled Identifier v1.0 document — specifically an entry with type: https://www.w3.org/ns/lws#OpenIdProvider whose serviceEndpoint matches the token's iss claim.

JSS profiles today expose the same information via the solid:oidcIssuer predicate. That works for existing Solid clients but not for LWS-aware verifiers, which look for the CID service[] shape.

Scope

Emit one CID service[] entry in the generated WebID profile, mirroring the already-present oidcIssuer value. Nothing else moves.

  • lws:OpenIdProvider is the only service type normatively defined in the four LWS10 FPWDs. pim:storage, ldp:inbox, etc. are not yet spec'd under LWS — leaving them alone until the vocabulary stabilizes.
  • verificationMethod[] is explicitly out of scope. Publishing public keys in a user's profile is a security-model change (the profile becomes authoritative for which keys can act for them). Tracking separately.

What changes

src/webid/profile.js — four small additions to generateProfileJsonLd:

  1. Two context namespace entries: cidhttps://www.w3.org/ns/cid/v1#, lwshttps://www.w3.org/ns/lws#.
  2. Two context term aliases: servicecid:service, serviceEndpointcid:serviceEndpoint.
  3. One new field in the output: a service[] array with a single lws:OpenIdProvider entry.
  4. Strip the #me fragment from webId to derive the document URL for the service entry's fragment id.

Nested service entries use the JSON-LD keywords @id and @type directly. CID 1.0's own context URL (https://www.w3.org/ns/cid/v1) provides id/type aliases for authors who prefer the shorter form, but since this profile uses inline term definitions rather than a context URL, we stick with the keywords — they're JSON-LD-native and don't depend on an out-of-band context fetch. A verifier that runs a JSON-LD processor (the expected behaviour for CID-conformant tooling) expands both forms identically.

Shape

Before

{
  "@context": {
    "foaf": "http://xmlns.com/foaf/0.1/",
    "solid": "http://www.w3.org/ns/solid/terms#",
    "schema": "http://schema.org/",
    "pim": "http://www.w3.org/ns/pim/space#",
    "ldp": "http://www.w3.org/ns/ldp#",
    "inbox": { "@id": "ldp:inbox", "@type": "@id" },
    "storage": { "@id": "pim:storage", "@type": "@id" },
    "oidcIssuer": { "@id": "solid:oidcIssuer", "@type": "@id" },
    ...
  },
  "@id": "https://test2.solidweb.app/profile/card.jsonld#me",
  "@type": ["foaf:Person", "schema:Person"],
  "foaf:name": "test2",
  "inbox": "https://test2.solidweb.app/inbox/",
  "storage": "https://test2.solidweb.app/",
  "oidcIssuer": "https://solidweb.app/",
  ...
}

After

{
  "@context": {
    "foaf": "http://xmlns.com/foaf/0.1/",
    "solid": "http://www.w3.org/ns/solid/terms#",
    "schema": "http://schema.org/",
    "pim": "http://www.w3.org/ns/pim/space#",
    "ldp": "http://www.w3.org/ns/ldp#",
    "cid": "https://www.w3.org/ns/cid/v1#",
    "lws": "https://www.w3.org/ns/lws#",
    "inbox": { "@id": "ldp:inbox", "@type": "@id" },
    "storage": { "@id": "pim:storage", "@type": "@id" },
    "oidcIssuer": { "@id": "solid:oidcIssuer", "@type": "@id" },
    "service": { "@id": "cid:service", "@container": "@set" },
    "serviceEndpoint": { "@id": "cid:serviceEndpoint", "@type": "@id" },
    ...
  },
  "@id": "https://test2.solidweb.app/profile/card.jsonld#me",
  "@type": ["foaf:Person", "schema:Person"],
  "foaf:name": "test2",
  "inbox": "https://test2.solidweb.app/inbox/",
  "storage": "https://test2.solidweb.app/",
  "oidcIssuer": "https://solidweb.app/",
  "service": [
    {
      "@id": "https://test2.solidweb.app/profile/card.jsonld#oidc",
      "@type": "lws:OpenIdProvider",
      "serviceEndpoint": "https://solidweb.app/"
    }
  ],
  ...
}

Properties

  • Zero removals. Every existing WebID predicate stays as-is, so Mashlib, solid-client-authn, rdflib.js etc. keep seeing the profile they see today.
  • Additive ~200 bytes on the wire per profile.
  • Fragment id (#oidc) resolves against the document URL — idiomatic JSON-LD and matches CID examples.
  • Existing pods are unaffected unless regenerated; new pods get the new shape on first creation.

Ship-it criteria

  • src/webid/profile.js emits the CID service[] entry.
  • New test in test/webid.test.js asserts the entry is present with the correct @type and serviceEndpoint mirroring oidcIssuer.
  • Full suite still green.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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