From efcee88f0547e0e96d01fc679861c412390eaf7a Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Tue, 30 Jun 2026 17:04:24 -0400 Subject: [PATCH] docs(test): add OIDC/MSC3861 test section + local MAS dev loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LOTUS_TESTING.md section N (N1-N6): OIDC login flow, session-persist-on-reload, token refresh, logout revocation, account-management link, and the non-OIDC regression check. Backed by dev/oidc-test/ — a runnable local Matrix Authentication Service + Synapse(msc3861) loop (compose skeleton, the Synapse experimental_features delta, and the public/config.json override) so the flow can be verified without a mozilla.org tester. Co-Authored-By: Claude Opus 4.8 --- LOTUS_TESTING.md | 44 ++++++++++++ dev/oidc-test/README.md | 112 +++++++++++++++++++++++++++++ dev/oidc-test/config.local.json | 7 ++ dev/oidc-test/synapse-msc3861.yaml | 16 +++++ 4 files changed, 179 insertions(+) create mode 100644 dev/oidc-test/README.md create mode 100644 dev/oidc-test/config.local.json create mode 100644 dev/oidc-test/synapse-msc3861.yaml diff --git a/LOTUS_TESTING.md b/LOTUS_TESTING.md index 613cdab82..284d27cb9 100644 --- a/LOTUS_TESTING.md +++ b/LOTUS_TESTING.md @@ -410,6 +410,50 @@ Settings → Appearance → theme picker → try each of the 5 new themes. --- +## N. OIDC / Next-Gen Auth login (MSC3861) — P4-6 + +The Lotus client can now sign into OIDC-native homeservers (ones that delegate +auth to a Matrix Authentication Service / MAS), e.g. mozilla.org. lotusguild's +own server is **not** MSC3861, so test EITHER against a **local MAS dev loop** +(full setup in `dev/oidc-test/README.md` — docker-compose + Synapse `msc3861` +delta + a `config.json` override) OR against **mozilla.org** with a real account. + +### N1. OIDC login flow (the core test) — needs a MAS homeserver + +1. On the login screen, select the OIDC homeserver (local `localhost:8008`, or `mozilla.org`). +2. **Expected:** instead of the username/password form, a single **"Continue with single sign-on"** button appears (password + legacy-SSO are suppressed for that server). +3. Click it → redirected to the provider's login page (MAS / `chat.mozilla.org`). +4. Authenticate there → redirected back to `…/auth/oidc/callback` → a brief "Signing you in…" spinner → you land in the app, logged in. + +**Expected:** no console CSP violations; you reach the room list as the OIDC user. + +### N2. Session persists across reload (token storage) + +After N1, hard-refresh the page. +**Expected:** you stay logged in — the OIDC session (access + refresh token + issuer/clientId/claims) was persisted (`cinny_refresh_token`, `cinny_oidc_*` keys in localStorage). + +### N3. Token refresh (long-lived session) + +Leave the session past the access-token lifetime (MAS default is short — or revoke the access token in the MAS admin UI to force a 401). +**Expected:** the client refreshes transparently (no logout); the stored access token rotates (reactive 401 refresh via the wired `OidcTokenRefresher`). + +### N4. Logout revokes at the issuer + +Log out from Settings. +**Expected:** back to login; OIDC tokens are revoked at the issuer's `revocation_endpoint` (best-effort) and all `cinny_*` / `cinny_oidc_*` keys are cleared. Logging back in works. + +### N5. Account-management deep-link + +Settings → Account. +**Expected:** on an OIDC server a **"Manage account"** card appears (opens the provider's account page in a new tab). On a non-OIDC server (lotusguild) the card is **absent**. + +### N6. Non-OIDC regression — password login unchanged + +Log into **matrix.lotusguild.org** (password) and **matrix.org**. +**Expected:** identical to before — username/password form (+ SSO button where offered). The OIDC path only activates when discovery advertises an issuer, so nothing changes for these servers. + +--- + ## Priority if you're short on time 1. **A4** (in-call banner) + **A3** (ringtone) — newest, most logic, hardest to reproduce. diff --git a/dev/oidc-test/README.md b/dev/oidc-test/README.md new file mode 100644 index 000000000..68dbd3b9c --- /dev/null +++ b/dev/oidc-test/README.md @@ -0,0 +1,112 @@ +# Local OIDC / next-gen-auth (MSC3861) test loop + +The Lotus client gained MSC3861/MSC2965 OIDC login (P4-6). lotusguild's own +homeserver is **not** MSC3861, so to exercise the flow without a mozilla.org +tester you need a local homeserver that delegates auth to a **Matrix +Authentication Service (MAS)**. This is the dev loop. + +> Status: the Lotus-client side is unit-tested + gate-green; this server loop is +> the manual end-to-end check. It hasn't been run in CI (no container runtime +> there), so treat version pins as a starting point and bump as needed. + +## 1. Stand up MAS + Synapse + +The simplest path is the **upstream MAS docker-compose quickstart** — it's +maintained and handles key generation + the database: + +(`docker compose` section). Use it to get MAS + Synapse + Postgres running, then +apply the two Lotus-specific deltas below. + +A minimal `compose.yaml` skeleton (generate MAS keys first — do **not** hand-write them): + +```yaml +services: + postgres: + image: postgres:16 + environment: { POSTGRES_USER: synapse, POSTGRES_PASSWORD: pw, POSTGRES_DB: synapse } + mas: + image: ghcr.io/element-hq/matrix-authentication-service:latest + command: server + ports: ['8090:8080'] # MAS issuer on http://localhost:8090 + volumes: ['./mas:/data'] + # First run once: `docker compose run --rm mas config generate -o /data/config.yaml` + # then edit /data/mas/config.yaml (see §1a) before `up`. + synapse: + image: ghcr.io/element-hq/synapse:latest + ports: ['8008:8008'] # client/federation API + volumes: ['./synapse:/data'] + depends_on: [postgres, mas] +``` + +### 1a. MAS `config.yaml` — the parts that matter +After `config generate` (which fills in `secrets.keys` + `encryption`), set: + +```yaml +http: + public_base: http://localhost:8090/ + issuer: http://localhost:8090/ +database: + uri: postgresql://synapse:pw@postgres/synapse +matrix: + homeserver: localhost # the server_name + endpoint: http://synapse:8008/ + secret: "REPLACE_WITH_A_LONG_SHARED_ADMIN_TOKEN" +clients: + - client_id: "0000000000000000000SYNAPSE" + client_auth_method: client_secret_basic + client_secret: "REPLACE_WITH_A_SHARED_CLIENT_SECRET" +passwords: # so you can create a local test account in the MAS UI + enabled: true +``` + +### 1b. Synapse `homeserver.yaml` — delegate auth to MAS +See `synapse-msc3861.yaml` in this folder; the key block is: + +```yaml +experimental_features: + msc3861: + enabled: true + issuer: http://localhost:8090/ + client_id: "0000000000000000000SYNAPSE" + client_auth_method: client_secret_basic + client_secret: "REPLACE_WITH_A_SHARED_CLIENT_SECRET" # == MAS clients[].client_secret + admin_token: "REPLACE_WITH_A_LONG_SHARED_ADMIN_TOKEN" # == MAS matrix.secret + account_management_url: "http://localhost:8090/account" +``` + +Create a test user via the MAS UI (`http://localhost:8090/`) or +`docker compose exec mas mas-cli manage register-user`. + +Sanity check discovery (the client relies on this): +```bash +curl -s http://localhost:8008/.well-known/matrix/client | jq '."m.authentication"' +# -> { "issuer": "http://localhost:8090/", "account": "http://localhost:8090/account" } +``` + +## 2. Point the Lotus dev client at it + +Run the client: `npm start` (vite dev). Override `public/config.json` so the +local server is selectable and custom servers are allowed: + +```json +{ + "defaultHomeserver": 0, + "homeserverList": ["localhost:8008"], + "allowCustomHomeservers": true, + "hashRouter": { "enabled": false, "basename": "/" } +} +``` + +Dynamic client registration handles the redirect URI automatically — it's +`/auth/oidc/callback` (e.g. `http://localhost:5173/auth/oidc/callback`), +and MAS allows `http://localhost` redirects in dev. + +## 3. Run the checklist + +See **section N** of `../../LOTUS_TESTING.md` for the actual pass/fail steps +(login redirect, callback, session-persist-on-reload, token refresh, logout +revocation, account-management link, and the non-OIDC-regression check). + +## Files here +- `synapse-msc3861.yaml` — the Synapse experimental-features delta. +- `config.local.json` — the Lotus `public/config.json` override. diff --git a/dev/oidc-test/config.local.json b/dev/oidc-test/config.local.json new file mode 100644 index 000000000..4a852f749 --- /dev/null +++ b/dev/oidc-test/config.local.json @@ -0,0 +1,7 @@ +{ + "defaultHomeserver": 0, + "homeserverList": ["localhost:8008"], + "allowCustomHomeservers": true, + "featuredCommunities": { "openAsDefault": false, "spaces": [], "rooms": [], "servers": [] }, + "hashRouter": { "enabled": false, "basename": "/" } +} diff --git a/dev/oidc-test/synapse-msc3861.yaml b/dev/oidc-test/synapse-msc3861.yaml new file mode 100644 index 000000000..00c9dc370 --- /dev/null +++ b/dev/oidc-test/synapse-msc3861.yaml @@ -0,0 +1,16 @@ +# Synapse experimental-features delta to delegate auth to a local MAS (MSC3861). +# Merge this into your test homeserver.yaml. The client_secret + admin_token MUST +# match the MAS config (clients[].client_secret and matrix.secret respectively). +experimental_features: + msc3861: + enabled: true + issuer: http://localhost:8090/ + client_id: "0000000000000000000SYNAPSE" + client_auth_method: client_secret_basic + client_secret: "REPLACE_WITH_A_SHARED_CLIENT_SECRET" + admin_token: "REPLACE_WITH_A_LONG_SHARED_ADMIN_TOKEN" + account_management_url: "http://localhost:8090/account" + +# With msc3861 enabled, Synapse disables its own password/SSO login and advertises +# `m.authentication` in /.well-known/matrix/client — which is exactly what the +# Lotus client's getOidcIssuer() reads to switch into the OIDC flow.