Spaces:
Running
Running
|
Download docs/STUDIO_IDENTITY_SETUP.md from basyx/MediaRouter: direct link, hf CLI and curl.
- Browser
- Download file 4.91 kB
-
https://huggingface.co/spaces/basyx/MediaRouter/resolve/main/docs/STUDIO_IDENTITY_SETUP.md
- Command line
-
hf download hf://spaces/basyx/MediaRouter/docs/STUDIO_IDENTITY_SETUP.md
-
curl -L -o STUDIO_IDENTITY_SETUP.md https://huggingface.co/spaces/basyx/MediaRouter/resolve/main/docs/STUDIO_IDENTITY_SETUP.md
4.91 kB
| # MediaRouter Studio identity and tenant isolation | |
| MediaRouter Studio authenticates users with Supabase on the Next.js server and forwards a short-lived, signed identity envelope to MediaRouter. The shared MediaRouter API token is a server-to-server transport credential; it must never be exposed to browser code. | |
| ## Required configuration | |
| Set these values in both environments: | |
| - **Studio / Vercel:** `STUDIO_IDENTITY_SECRET` and `MEDIAROUTER_API_TOKEN`. Keep them server-only; do not use a `NEXT_PUBLIC_` prefix. | |
| - **MediaRouter / Hugging Face Space:** `STUDIO_IDENTITY_SECRET` with the exact same secret value, plus the existing API authentication and production database configuration. | |
| Use a cryptographically random secret of at least 32 bytes. Generate one with a password manager or a secure local random generator. Do not paste it into source control, logs, or chat. Restart/redeploy both services after setting it. | |
| The Studio proxy signs the UTF-8 bytes of four newline-separated values in this order: timestamp (Unix seconds), Supabase user ID, normalized email, display name. It uses HMAC-SHA256 and sends the lowercase hexadecimal signature in `x-mr-studio-signature`. The backend validates the signature in constant time and rejects envelopes more than 300 seconds from server time. | |
| ## Tenant onboarding is explicit | |
| A valid Supabase session proves identity, but it does **not** automatically grant a MediaRouter workspace. Before a user can use tenant-backed Studio APIs, the backend security database must contain: | |
| 1. An active `users` row whose `subject` exactly matches the Supabase user ID. | |
| 2. Exactly one active `workspace_memberships` row for that user, linked to an active `workspaces` row. | |
| 3. A supported membership role: `owner`, `admin`, `developer`, `operator`, `viewer`, or `member`. | |
| Users with no active membership or more than one active workspace membership are denied. This is deliberate: the current Studio identity envelope has no workspace selector, and the backend must not guess a tenant. Do not solve onboarding by trusting a workspace ID from a browser request or by assigning every newly signed-in user an owner role. | |
| For a controlled first-user bootstrap, an operator with access to the backend's configured security database can run the explicit CLI command from the backend project environment: | |
| ```sh | |
| python -m app.security.cli provision-studio-user \ | |
| --subject "<exact Supabase auth user ID>" \ | |
| --display-name "<display name>" \ | |
| --workspace-slug "<unique-lowercase-workspace-slug>" \ | |
| --workspace-name "<workspace name>" \ | |
| --role owner | |
| ``` | |
| This command refuses to reassign an already-provisioned subject or reuse an existing workspace slug. It requires direct operator/database access and must not be exposed as an unauthenticated HTTP endpoint. For subsequent members, use the authorized invitation workflow; invitation acceptance still needs to be wired to the identity provider before invitations alone grant access. | |
| ## Authorization behavior | |
| The backend treats the shared API key as transport authentication only when a signed Studio identity is present. It resolves the Supabase subject against persisted backend membership, replaces the key's tenant identity with that persisted principal, and intersects API-key scopes with the membership role's default scopes. Workspace owners/admins are mapped to the backend `developer` capability set, not the global API `admin` role. Viewer/member access is restricted to the viewer capability set. | |
| If any Studio identity header is present, the complete envelope and signature are required. The Studio proxy also fails closed when it cannot validate a Supabase session; it must not forward the shared token as a fallback for an unidentified browser request. | |
| ## Production verification checklist | |
| - [ ] Set the same random `STUDIO_IDENTITY_SECRET` in Vercel and the HF Space. | |
| - [ ] Confirm `MEDIAROUTER_API_TOKEN` is only a server-side Vercel environment variable. | |
| - [ ] Provision one explicit backend user and workspace membership for each Studio user, or implement an authorized invitation flow. | |
| - [ ] Use a non-superuser tenant database role and verify forced RLS policies on production tables; a passing application-level check alone is not proof of database isolation. | |
| - [ ] Test with two distinct Studio accounts: create/read/update/delete a project and access an asset/job in account A, then confirm account B cannot read, mutate, cancel, or download A's resources. | |
| - [ ] Test expired and tampered signatures, disabled users/memberships/workspaces, and users with zero or multiple active memberships. | |
| - [ ] Run the backend unit/integration tests and inspect production logs for denied cross-tenant access before merging/deploying. | |
| This document describes the intended configuration and checks; it is not evidence that the live deployment has been configured or that the checklist has passed. | |