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:

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.