T-HUB/docs/design/2026-10-13-files-oidc-sso.md
glass beadian 5bc81c16f2 docs: files SSO design pass — Hub as the OIDC issuer for oCIS
Phase 1 kills the navy login wall (provider + PKCE + auto-consent for the
first-party oCIS web client); phases 2-3 move uploads into personal drives
and share collective folders into them. Mirrors the Matrix JWT broker: the
Hub is the identity, oCIS is a relying party.
2026-10-13 16:52:33 +00:00

86 lines
4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Files SSO design — Hub as the OIDC issuer for oCIS
Status: proposed (design pass; not implemented)
Date: 2026-10-13
Related: docs/design/2026-10-12-collectives-architecture.md, brand review P0 #2
(files.occupymedia.cc navy login wall), matrix-sso module (chat SSO, shipped).
## Problem
The Hub's Drive view embeds oCIS web (files.occupymedia.cc). Today:
- No Hub user has an oCIS account. The API reaches oCIS through one shared
service account (`FILES_OCID_USER`); the collective Library lives in that
account's space.
- The embedded oCIS web shows its own sign-in screen for a login the user
does not have, in ownCloud's default navy/white theme — the single worst
brand break measured in the review.
## Decision
The Hub becomes the OIDC identity provider; oCIS trusts it as its external
issuer. This mirrors what just shipped for chat: the Hub is already the
identity provider for Matrix (JWT broker). Files becomes the second relying
party of the same identity, not a third account system.
Rejected alternative: a standalone IdP (Authelia/Authentik/Keycloak). It adds
a service to run and a second admin surface for one relying party; the Hub
already holds the session, the RBAC roles, and the username namespace.
## Flow (target state)
1. User opens `/files/drive` in the Hub. Their Hub session cookie proves who
they are.
2. The embedded oCIS web redirects to `https://api.occupymedia.cc/oidc/authorize`
(client id `web`, PKCE required).
3. The Hub is already signed in → no login prompt, no consent screen for this
first-party client (auto-approve). A short-lived code returns to oCIS.
4. oCIS exchanges the code at `/oidc/token`, reads claims
(`preferred_username` = Hub username, `email`, `name`), and provisions the
oCIS account on first login (oCIS does this natively when
`OCIS_OIDC_ISSUER` points at an external issuer).
5. The user lands in their own drive. The navy wall is gone because there is
no wall.
## What the Hub must add
- `apps/api/src/oidc/`: an OIDC provider module —
`/.well-known/openid-configuration`, `/oidc/authorize`, `/oidc/token`,
`/oidc/userinfo`, `/oidc/jwks`. Signing keys in the existing vault pattern
(ES256 or RS256, rotated like DEKs). Session binding to the existing Hub
session cookie; codes single-use, ≤60 s TTL, PKCE S256 enforced.
- Auto-consent policy: client id `web` (the oCIS web app) is first-party and
skips the consent screen. Any other client id requires explicit consent —
fail closed.
- Claim mapping: `preferred_username` must equal the Hub username verbatim
(same invariant the Matrix SSO module already enforces: Hub usernames are a
subset of the localpart grammar, case-folded identity is refused).
## What oCIS must change
- `OCIS_OIDC_ISSUER=https://api.occupymedia.cc/oidc`
- `WEB_OIDC_CLIENT_ID=web`, scope `openid profile email`
- oCIS auto-provisions accounts from claims (default behaviour with an
external issuer). The `FILES_OCID_USER` service account stays for the
Library's WebDAV path.
## Phases
1. **Provider + sign-in** (≈1–2 days): the module above; Drive view switches
`authMode` to `"oidc"`; the navy wall disappears.
2. **Personal drives** (≈1 day): uploaded files land in the user's own drive;
the Library keeps serving collective folders from the service account.
3. **Share-through** (≈1 day, optional): group folders shared into members'
drives so the Drive tab also shows collective Library content; only then
consider deprecating the Library tab.
## Security notes
- The OIDC provider must never accept the service-account identity for a
browser session; tokens are minted only from a live Hub session.
- Logout: Hub logout revokes the session cookie; oCIS tokens expire on their
own TTL (oCIS refresh behaviour is issuer-driven). Single-logout signaling
to oCIS is a nice-to-have, not a blocker.
- The issuer URL must be exactly `https://api.occupymedia.cc/oidc` everywhere
(issuer discovery, oCIS config, token audience) — mismatch breaks token
validation.