Auth & audiences setup
The portal supports two authentication modes: supabase (OAuth and email/password, with in-app audience management) and password (bcrypt-hashed secrets in environment variables, a developer fallback). Use supabase for all real deployments.
Choosing a mode
Section titled “Choosing a mode”Set AUTH_PROVIDER in your .env (or in the Netlify environment variables):
AUTH_PROVIDER=supabaseOmit AUTH_PROVIDER or set it to password to use password-only auth. In password mode, audiences are defined entirely by the VIEWER_<NAME>_PASSWORD environment variables — they cannot be managed in the editor UI.
Supabase mode
Section titled “Supabase mode”Shared Supabase project
Section titled “Shared Supabase project”All client sites share one Supabase project. Every *.drawn.guide site does OAuth, invite, and password-reset flows against the same Auth instance. The three required env vars are the same across all client sites:
SUPABASE_URL=https://your-project.supabase.coSUPABASE_ANON_KEY=your-anon-keySUPABASE_SERVICE_ROLE_KEY=your-service-role-keyDefault audience
Section titled “Default audience”Each site has a default viewer audience seeded at site creation. The isDefault flag is a Supabase-only concept — it marks the audience that viewers fall into when they authenticate without being assigned to a named audience. This is set in the database at provisioning time and does not appear in password-mode sites.
Critical Supabase dashboard configuration
Section titled “Critical Supabase dashboard configuration”The following rules apply to the Supabase dashboard (the production source of truth). Do not apply them via supabase config push — the monorepo’s supabase/config.toml has site_url set to localhost and would clobber production settings.
Site URL — set to a single concrete origin:
https://acme.drawn.guideWildcards are rejected in the Site URL field and a wildcard entry silently breaks the fallback path for every site. Pick one concrete domain as the Site URL (typically the main client site or the first site created).
Redirect URL allow-list — restrict to platform-controlled paths:
https://*.drawn.guide/edit/loginhttps://*.drawn.guide/edit/login/callbackThese are the only two paths any auth flow redirects to: OAuth and invite/reset flows use /edit/login/callback; the existing-user invite login link uses /edit/login. Path-restricting the allow-list means a wildcard subdomain entry cannot be abused to redirect to an arbitrary page on any drawn.guide subdomain.
Never add a bare *.netlify.app entry. netlify.app is a shared hosting domain — any Netlify tenant could register a subdomain and become a valid redirect target in your allow-list, enabling an open-redirect attack that could steal auth codes.
OAuth redirect_to
Section titled “OAuth redirect_to”The portal builds the OAuth redirect_to parameter from the live request origin, not from the build-time SITE environment variable. This is required because Netlify’s URL environment variable (which Astro bakes into import.meta.env.SITE) can resolve to the *.netlify.app host instead of the custom domain — making redirect_to unmatched in the allow-list and landing the PKCE callback on a different origin from where the verifier cookie was set.
Any custom auth flow you add must derive its redirect origin from the incoming request, not from import.meta.env.SITE.
Password mode
Section titled “Password mode”In password mode, audiences are defined by environment variables. Each audience needs a name (the <NAME> suffix), a bcrypt password hash, and optionally a display color:
VIEWER_INTERNAL_PASSWORD=\$2b\$10\$...VIEWER_INTERNAL_COLOR=#10b981VIEWER_EXTERNAL_PASSWORD=\$2b\$10\$...VIEWER_EXTERNAL_COLOR=#3b82f6See Environment variables for the bcrypt hash generation command and the \$-escaping requirement.
Audience settings are read-only in the editor UI when running in password mode. To add or remove an audience, edit the environment variables and redeploy.