feat(portal): real OCIS storage data via refresh-token service auth
The Storage page + endpoint landed earlier but had no working OCIS backend credential. OCIS has no service-account/client-credentials grant and trusts a single issuer, and basic auth resolves no user in our external-IdP setup — so authenticate OcisClient via an OIDC refresh-token bootstrap instead: - One-time headless login of svc-platform-api against the ocis provider (public client ocis-web, issuer .../o/ocis/) yields a refresh token, persisted in Mongo (ocis_credentials) and rotated on every use. - OcisClient mints access tokens with the refresh_token grant; the service user holds the OCIS admin role (OCIS_ADMIN_USER_ID) so libregraph ListAllDrives works. - scripts/bootstrap-ocis.mjs re-runs the bootstrap if the token lapses. - Dashboard Plan card gains a storage capacity bar beside seats; hidden when storage is unavailable. - compose + .env.example: OCIS service OIDC env and admin user id. - docs/NEXT-STEPS: document the mechanism and the dead-end alternatives.
This commit is contained in:
+23
-4
@@ -124,10 +124,29 @@ Need a minimal JMAP client that wraps `Domain/set` (create), `Domain/get`
|
||||
via the persistent admin's bearer token from the OAuth flow we already use
|
||||
for the web UI.
|
||||
|
||||
**OCIS (libregraph)** — `POST /graph/v1.0/drives` with body
|
||||
`{ "name": "<slug>", "driveType": "project" }`. Needs service-to-service
|
||||
auth: either an OIDC client_credentials grant (requires registering a new
|
||||
Authentik provider for the worker) or the IDM admin user's bearer token.
|
||||
**OCIS (libregraph)** — space *provisioning* is still stubbed:
|
||||
`POST /graph/v1.0/drives` with body `{ "name": "<slug>", "driveType":
|
||||
"project" }` to create a tenant's project space, then assign it.
|
||||
|
||||
**OCIS read auth (done — powers the customer-admin Storage page).** OCIS has
|
||||
*no* backend service-account/client-credentials grant and trusts exactly one
|
||||
issuer, and basic auth doesn't resolve a user in our external-IdP setup. The
|
||||
working mechanism is a **refresh-token bootstrap**:
|
||||
|
||||
1. A dedicated Authentik user `svc-platform-api` (with an email — OCIS
|
||||
autoprovision rejects empty emails) logs in **once** against the *ocis*
|
||||
provider (public client `ocis-web`, per-provider issuer `.../o/ocis/` — the
|
||||
one OCIS trusts). Run it headlessly:
|
||||
`docker compose exec platform-api node /app/scripts/bootstrap-ocis.mjs`.
|
||||
The refresh token is persisted in Mongo (`ocis_credentials`).
|
||||
2. `OcisClient` mints access tokens with the `refresh_token` grant and persists
|
||||
the rotated token each call (Authentik rotates on every use).
|
||||
3. The svc user needs the OCIS **admin** role for `ListAllDrives` — granted via
|
||||
`OCIS_ADMIN_USER_ID=<svc OCIS account UUID>` on the ocis service.
|
||||
|
||||
Note: the "global" issuer mode is **not** an option — its issuer is the
|
||||
Authentik root, which has no `.well-known/openid-configuration`, so OCIS can't
|
||||
validate tokens against it.
|
||||
|
||||
### Authentik API examples (for the eventual user-creation flow)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user