MediaRouter / docs /STUDIO_IDENTITY_SETUP.md
basyx's picture
Apply PR #7 security changes directly to main: docs/STUDIO_IDENTITY_SETUP.md
6fc69c5 verified
|
Raw History Blame Contribute Delete
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.