jeswr / jeswr/solid-openid-client

Design review: @jeswr/solid-openid-client (openid-client v6 Solid-OIDC engine) — decisions for maintainer steer

Open
#1 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

## Design summary + decisions for maintainer review

🤖 PSS agent — @jeswr's agent for `prod-solid-server` / the Solid app+Pod-Manager suite.

`@jeswr/solid-openid-client` is a **Solid-OIDC engine wrapping panva's `openid-client` v6** — the dominant, audited OAuth2/OIDC client — for **server-side Node apps** (CLIs, services, bots, agents) that want Solid-OIDC login without a bespoke implementation. Per the standing "don't block on greenlights" rule, I made the design choices below, documented them, and am filing this for you to steer later.

### What it does (P1, built)
- Issuer discovery (`.well-known/openid-configuration`) via openid-client.
- Authorization-code + **PKCE (S256)** flow, **`state` + `nonce` always** generated and validated.
- **DPoP-bound tokens** (RFC 9449) — composes `@jeswr/solid-dpop` (do NOT reimplement DPoP).
- Token **refresh** (DPoP-bound, rotation-aware).
- Scopes `openid webid offline_access`; reads the `webid` claim **fail-closed**.
- A **DPoP-attaching authed `fetch`** — `ath`-bound to the access token, §8 `DPoP-Nonce` retry.

Public API: `createSolidOidcClient({ issuer, clientId|client, redirectUri, scope?, dpopKeyPair?, fetch?, allowInsecure? })` → `{ authorizationUrl, handleCallback, refresh, fetch, currentTokens, currentWebId, dpopKeyPair }`.

### Design decisions (your call to steer)
1. **Wrap openid-client v6, don't fork.** Lean on it for discovery/PKCE/code-exchange/ID-token validation/refresh; add only the Solid seams.
2. **Compose `@jeswr/solid-dpop` for DPoP, both legs.** Key generation (ES256/asymmetric/thumbprint) + the **resource-leg `ath` proof** use `@jeswr/solid-dpop`; the **token-endpoint proofs** use openid-client's own DPoP handle bound to the *same* keypair (it tracks the server `DPoP-Nonce` across token requests for us). → **Q: happy with this split, or should the resource leg also go through openid-client's `fetchProtectedResource` / the token leg also through `@jeswr/solid-dpop`?**
3. **Client Identifier Document is the PRIMARY client path; DCR is a documented secondary seam** (supply a registered `client` identity yourself). → **Q: should the package also offer a built-in DCR helper, or keep it caller-driven?**
4. **Token storage is an injectable seam** — the package never persists; the consumer stores `currentTokens()` + `dpopKeyPair` (the refresh-token `jkt` binding requires the same key). → **Q: want an optional bundled file/IndexedDB store, like `@jeswr/solid-dpop`'s `sessionStore`?**
5. **`openid-client` is a peerDependency** (consumer-resolved, audited copy); `@jeswr/solid-dpop` is bundled into the committed `dist/` (esbuild-inlined) so `github:` install works under `ignore-scripts=true`. `jose` stays external.
6. **Redirect handling is caller-owned** — `authorizationUrl()` returns the URL + transient `state`; `handleCallback()` takes the redirect URL/params + that state. No bundled loopback listener (a documented seam for CLIs). → **Q: want a bundled loopback-listener helper for the CLI case (like `@jeswr/solid-dpop`'s `cliLogin`)?**

### Security posture
PKCE S256 always, state+nonce always validated, asymmetric DPoP only, fail-closed on a missing/non-`http(s)` `webid`, no token logging, TLS issuers (http only for a loopback dev OP). Tested exhaustively (38 vitest cases) against a **faithful Map-backed mock OP** (real ES256 ID tokens, real JWKS, real PKCE S256 — no live IdP). roborev-clean (codex).

### Relationship to `@jeswr/solid-dpop`
`@jeswr/solid-dpop` already has a `jose`-based auth-code `cliLogin`. This package is the **`openid-client`-backed** alternative — same DPoP primitives, but the OIDC mechanics (discovery, PKCE, ID-token validation, refresh) come from the dominant audited client rather than hand-rolled. → **Q: keep both (jose-native + openid-client-backed), or converge?**

This is **experimental / AI-agent-generated**; review before relying on it. Happy to adjust any of the above.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reviewing the createSolidOidcClient API and the listed design decisions, especially the DPoP split, DCR, token storage, and redirect handling. Run the 38 Vitest cases against the Map-backed mock OP to understand the current behavior. Done requires maintainer decisions on the open questions and an agreed direction for the experimental package.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js
Domain
authentication, backend, backend-api-design, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.