Skip to content

SSO Implementation Plan

Current Auth Setup

  • Provider: Supabase Auth
  • Existing methods: Magic link (email OTP), Google OAuth, LinkedIn OAuth
  • JWT verification: Custom middleware in workers/api/src/middleware/auth.ts (ES256 + HS256)
  • Multi-tenant: Users belong to a tenant via profiles.tenant_id; tenant resolved by domain, header, or user profile

Goal

Allow enterprise tenants to require SSO login for their users via their organization’s identity provider (IdP). Users visiting a tenant’s domain would authenticate through their company’s IdP instead of (or in addition to) magic link / social OAuth.

Tier 1 β€” Must Have

ProtocolProvider ExamplesWhy
SAML 2.0Okta, Azure AD (Entra ID), OneLogin, Ping Identity, ADFSIndustry standard for enterprise SSO. Required by most Fortune 500 procurement teams.
OpenID Connect (OIDC)Azure AD, Okta, Google Workspace, Auth0Modern alternative to SAML. Many IdPs support both. Simpler to implement.

Tier 2 β€” Nice to Have

ProviderWhy
Google Workspace (domain-restricted)Already have Google OAuth β€” restrict to a specific domain for a tenant
Microsoft Entra ID (Azure AD)Dominant in government and education (key accessibility markets)
OktaMost common dedicated IdP in mid-market enterprise

Tier 3 β€” Future

ProviderWhy
PingFederate / PingOneCommon in healthcare and finance
OneLoginGrowing in mid-market
LDAP (via SAML bridge)Legacy enterprises β€” handle via SAML rather than direct LDAP
SCIM provisioningAuto-create/deactivate users when added/removed in IdP

Implementation Approach

Supabase has built-in SAML 2.0 SSO support on the Pro plan and above. This is the path of least resistance since we already use Supabase Auth.

How it works:

  1. Register enterprise IdP via Supabase Management API or Dashboard
  2. Map the IdP to a tenant domain (e.g., acme.com users β†’ SAML via Okta)
  3. Supabase handles SAML assertion parsing, user creation, and JWT issuance
  4. Our existing JWT verification middleware works unchanged

Supabase SSO API:

Terminal window
# Register a SAML provider for a tenant
curl -X POST https://vuvwmfxssjosfphzpzim.supabase.co/auth/v1/admin/sso/providers \
-H "Authorization: Bearer SERVICE_ROLE_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "saml",
"metadata_url": "https://idp.acme.com/metadata.xml",
"domains": ["acme.com"],
"attribute_mapping": {
"keys": {
"email": { "name": "email" },
"full_name": { "name": "displayName" }
}
}
}'

Login flow:

User visits tenant domain β†’ enters email β†’ backend checks domain for SSO β†’
if SSO: redirect to /auth/v1/sso with domain param β†’ IdP login β†’ callback β†’ JWT
if no SSO: normal magic link / OAuth flow

Frontend change (login page):

  1. Add an email input step before showing auth methods
  2. On email submit, call a new endpoint GET /api/auth/sso-check?email=user@acme.com
  3. If SSO is configured for that domain, redirect to Supabase SSO endpoint
  4. If not, show the existing magic link / OAuth options

Option B: External SSO Service (BoxyHQ, WorkOS)

If Supabase SSO proves limiting (e.g., need OIDC federation, SCIM, or more IdP control):

  • WorkOS β€” turnkey SSO + Directory Sync. $125/mo per connection. Good DX.
  • BoxyHQ (jackson) β€” open-source SAML/OIDC proxy. Self-hostable. Free.

These act as a SAML/OIDC proxy: enterprise IdP β†’ WorkOS/BoxyHQ β†’ our app gets a standard OAuth token.

Recommendation

Start with Supabase SSO (Option A). It requires no new dependencies, our JWT middleware already works, and SAML covers 90%+ of enterprise IdP requirements. Move to Option B only if we hit limitations.

Database Changes

-- Add SSO configuration to tenants
ALTER TABLE tenants ADD COLUMN sso_enabled boolean NOT NULL DEFAULT false;
ALTER TABLE tenants ADD COLUMN sso_provider_id text; -- Supabase SSO provider ID
ALTER TABLE tenants ADD COLUMN sso_enforce boolean NOT NULL DEFAULT false; -- Force SSO (no magic link fallback)
ALTER TABLE tenants ADD COLUMN sso_domains text[]; -- Email domains routed to this SSO provider
-- Track SSO provider metadata for admin UI
CREATE TABLE tenant_sso_config (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
provider_type text NOT NULL CHECK (provider_type IN ('saml', 'oidc')),
provider_name text NOT NULL, -- "Okta", "Azure AD", etc.
metadata_url text, -- IdP metadata URL (SAML)
issuer_url text, -- OIDC issuer
client_id text, -- OIDC client ID (encrypted)
supabase_provider_id text, -- ID returned by Supabase SSO API
status text NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'active', 'disabled')),
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
UNIQUE(tenant_id)
);
ALTER TABLE tenant_sso_config ENABLE ROW LEVEL SECURITY;

API Endpoints

MethodPathPurpose
GET/api/auth/sso-check?email={email}Check if email domain has SSO configured; return redirect URL if so
POST/api/tenant-admin/ssoConfigure SSO for a tenant (admin only)
GET/api/tenant-admin/ssoGet current SSO config for a tenant
DELETE/api/tenant-admin/ssoRemove SSO config for a tenant
POST/api/tenant-admin/sso/testInitiate a test SSO login

Frontend Changes

Login Page (/auth/login)

  1. Email-first flow: Show email input before auth method buttons
  2. SSO detection: On email blur/submit, call /api/auth/sso-check
  3. SSO redirect: If SSO configured, show β€œSign in with [Company] SSO” button that redirects to Supabase SSO endpoint
  4. Fallback: If sso_enforce is false, also show magic link / OAuth options
  5. Direct URL: Support ?sso=domain.com query param for bookmarkable SSO login links

Tenant Admin (/tenant-admin/sso)

  • Upload IdP metadata XML or enter metadata URL
  • Select provider type (SAML or OIDC)
  • Test SSO connection
  • Toggle enforcement (SSO-only vs SSO + magic link)
  • View SSO login activity / errors

Onboarding Flow for Enterprise Customers

  1. Customer purchases Enterprise credit pack or contacts sales
  2. We create a tenant with their domain in tenant_domains
  3. Customer provides IdP metadata URL (or XML file)
  4. We register the SAML provider via Supabase SSO API (or admin UI does it)
  5. Test login with customer’s IT admin
  6. Enable sso_enforce if customer requires SSO-only access
  7. Customer’s users visit the tenant domain and authenticate via their IdP

Security Considerations

  • Domain verification: Verify tenant owns the domain before allowing SSO (DNS TXT record or email to domain admin). Already partially handled by tenant_domains.verified.
  • SSO enforcement: When sso_enforce = true, reject magic link and OAuth logins for users with matching email domains.
  • JIT provisioning: Auto-create user profiles on first SSO login (Supabase handles this). Set tenant_id based on the SSO provider’s tenant.
  • Session duration: Enterprise tenants may want shorter session TTLs. Add session_ttl_hours to tenant config.
  • Audit logging: Log all SSO login attempts (success/failure) for enterprise compliance.