Skip to main content

Multi-Tenant Auth & User Model — Provider Comparison

Status: Research / discussion artifact. This is intentionally not an implementation plan. The decision it informed lives in ADR-017; the implementation plan lives in 2026-04-09 WorkOS Auth Implementation.

Supersedes (in scope): 2026-03-01-user-authentication-plan.md, which proposed a roll-your-own approach (GitHub OAuth for admins + Resend magic link for clients). That plan does not address multi-tenant data model, per-tenant SSO, SCIM, Admin Portal, /t/:slug URL scoping, or the SecurityV0 super-admin switcher — all of which are explicit requirements here. Treat the older plan as an input, not the path forward.

Last updated: 2026-04-10 — added executive summary, detailed pricing deep-dive with COGS analysis, and cost optimization strategies.


Executive summary

Quick read for decision-makers. Jump to any section via the links below.

The problem

sv0-platform has no real authentication. Enterprise customers cannot be onboarded (no SAML/OIDC), our team switches tenants by editing localStorage, and there is no per-tenant configuration. This is a sales blocker.

The three viable options

WorkOSClerkStytch B2B
Per-customer SSO cost$125/mo ($1,500/yr) at 1-15; $50/mo at 101-200$75/mo ($900/yr) at 2-15; $15/mo at 500+$125/mo ($1,500/yr); no published volume tiers
Base cost$0 (1M MAU free)$20-25/mo + $0.02/MRU overage$0 (10K MAU free) + $0.10/MAU overage
Self-serve Admin PortalBest-in-classNo direct equivalentIncluded, embeddable
SCIMFirst-classNot GA (roadmap/Enterprise only)First-class, included free
Time to first login~3-5 days~2-3 days~5-7 days
CISO sellabilityStrong B2B brandB2C reputationNewer, less known
COGS impact at $45k ACV16.7% of COGS budget10% of COGS budget16.7% of COGS budget

Full comparison matrix · Detailed pricing deep-dive · Cost optimization strategies

Key finding: not every client needs SSO — and free auth methods work for real clients

The $125/connection/month SSO price is not WorkOS-specific — Stytch charges identically. But that cost only applies to enterprise customers whose IT team demands IdP-level control (SAML/OIDC). Many real paying clients — especially smaller companies and channel deals — can use free auth methods:

Auth methodCost in WorkOSViable for paying clients?
Google OAuth ("Sign in with Google")$0Yes — any client using Google Workspace
Microsoft OAuth$0Yes — any client using Microsoft 365
GitHub OAuth$0Yes — developer-focused clients
Magic link (email OTP)$0Yes — any client
SAML/OIDC SSO$125/moRequired only when client IT demands IdP control

Auth method tiering deep-dive · Blended COGS model

Recommendation

WorkOS remains the recommendation for technical and operational reasons (Admin Portal, B2B data model, CISO brand). The SSO pricing concern is less severe than it initially appears because most channel clients can use free social login + domain verification. See Auth Method Tiering for the analysis and Cost Optimization Strategies for additional levers.

DocumentPurpose
ADR-016: Multi-Tenant Auth ArchitectureVendor-independent architecture decisions
ADR-017: WorkOS as Auth ProviderVendor selection decision and rationale
13 — Authentication & User ManagementLiving architecture doc
WorkOS Auth Implementation PlanPhased implementation plan

Context

sv0-platform today has no real auth model:

  • Backend (src/api/middleware/auth.ts): JWT/JWKS scaffolding exists but REQUIRE_AUTH=false is the default. When off, every request gets principalId: "dev-auth-bypass", wildcard scopes, and whatever X-Tenant-Id header is sent. When on, it verifies a JWT against a configured JWKS endpoint — but there is no user directory to cross-check the sub claim against.
  • Tenants: No tenants collection. Tenant is a denormalized string on every document in all 17 Mongo collections. Tenants are implicitly created on first write. No metadata, no owner, no config.
  • Users: No users collection. AuthContext is just { principalId, method, scopes, tenantId } — built per-request, never persisted.
  • UI (ui/src/context/auth-context.tsx, ui/src/pages/SettingsPage.tsx): Tenant ID + API key are entered manually into a form, stored in localStorage under sv0-auth, and injected into every request as x-tenant-id / x-api-key. No login page. No OTP. No magic link. No tenant list. No /t/:slug URL scoping.
  • Cloudflare Access: app.securityv0.com and dev.securityv0.com sit behind CF Zero Trust, but the backend does not read Cf-Access-Jwt-Assertion. CF Access is currently a network gate only.
  • Per-tenant config (Jira links, connector creds, feature flags): does not exist.

What the user wants:

  1. Real enterprise-grade auth: per-tenant IdP (SAML/OIDC), because a Fortune 500 prospect asking to install today cannot be onboarded.
  2. A lightweight demo path (magic link / email OTP) that we can keep for small prospects and trials.
  3. Per-tenant configuration surface (auth, Jira, connectors, branding).
  4. SecurityV0 super-admins (our team) that automatically see every tenant, with a dropdown to switch between them instead of editing localStorage.
  5. Shareable URLs that encode tenant + page, so two team members can paste a link and land on the same view of the same customer.
  6. Tenant-aware configuration that we pre-provision now but can move to self-service later.

The decision point: which auth provider (or no provider) anchors this. Everything else — data model, URL scheme, admin switcher — is downstream of that choice and is largely the same work regardless.


Evaluation criteria

Each provider is scored against what this product actually needs. Weights reflect the requirements above.

CriterionWhy it matters for sv0
Enterprise SSO per tenant (SAML + OIDC)Non-negotiable for the Fortune 500 install scenario. Each customer brings their own IdP (Okta, Entra ID, Ping, Google Workspace).
Self-serve SSO onboarding (admin portal)A customer IT admin must be able to set up their own SAML connection without us writing code. Otherwise every new customer is a ticket for us.
SCIM / directory syncEnterprise customers want auto-provisioning and deprovisioning. Not day-1 critical but a fast follow.
Magic link / passwordlessFor demos, POCs, and smaller customers who won't set up SSO.
B2B multi-tenant model built-in (Organizations, memberships, roles)We shouldn't reinvent user↔tenant↔role tables.
Cross-tenant super-adminSecurityV0 team needs to see and act on every tenant. Not all providers model this cleanly.
React SDK qualityUI is React + React Router v6. Less code = less risk.
Node/Express backend SDKBackend is Node 24 ESM.
Pricing at our stageWe have ~0 paying customers today. Free tier matters. Per-MAU pricing that explodes at scale is a trap.
Vendor lock-in / exit costMigrating auth later is painful. OIDC-compliant providers are safer than ones with proprietary session models.
Implementation effortTime-to-first-working-login.

Providers considered

1. WorkOS

What it is: A B2B-focused auth platform. Started as "SSO as an API" (a drop-in SAML/OIDC broker) and has since grown into a full stack: AuthKit (hosted login UI), Organizations, SSO, Directory Sync (SCIM), Magic Auth, Admin Portal, Audit Logs. Heavily used by YC-ish B2B SaaS companies that sell into enterprise (Vercel, PlanetScale, Webflow).

Mental model:

  • Organizations = tenants. You create a WorkOS Organization per customer.
  • Users live in a shared directory but are members of one or more Organizations.
  • Connections = a tenant's IdP config (one SAML or OIDC connection per Organization).
  • Admin Portal = a magic link you generate and email to a customer IT admin; they configure their own SAML connection in a hosted UI without talking to us.
  • AuthKit = a hosted login page (like Auth0's Universal Login) that handles the entire flow. Your app does an OAuth2-style redirect to AuthKit and gets back a session.

How it would work in sv0:

  1. Backend: add @workos-inc/node. Replace verifyAndAttach() with WorkOS session verification. On first login, upsert users and memberships rows keyed by WorkOS user.id + organization.id.
  2. Frontend: replace the Settings tenant form with a "Sign in" button that redirects to AuthKit. After callback, store the WorkOS session cookie; use the organizations the user belongs to populate the tenant switcher.
  3. SecurityV0 super-admin: create one WorkOS Organization called securityv0-internal. Any user in that org (enforced by an @securityv0.com email domain rule) gets a role: super_admin flag in our own memberships table, which grants access to all tenants in the tenant switcher.
  4. New customer onboarding: we create a WorkOS Organization + send them an Admin Portal link. They configure their Okta/Entra ID connection themselves. Done.
  5. Demo customers: we skip the Admin Portal and flip the Organization to "Magic Link" — user enters email, gets a one-time link.

Pros:

  • Best-in-class enterprise SSO UX. Admin Portal alone saves weeks of work per customer.
  • Strong B2B data model (Organizations + memberships + roles) maps 1:1 to what we need.
  • SCIM/Directory Sync is first-class and uses the same Admin Portal.
  • OIDC-compliant — we can migrate off if we need to.
  • Well-documented, stable SDKs, used by companies at our target scale.

Cons:

  • Pricing: Free up to 1M MAU for AuthKit + Magic Auth + 1M Directory Sync users, but SSO connections are $125/connection/month after the first 1M users. In practice: free until we have real paying enterprise customers, then $125/month per enterprise customer (which is trivial compared to ACV).
  • Vendor has a say in your login UX if you use AuthKit's hosted page (you can self-host the form with their lower-level APIs instead).
  • Super-admin cross-tenant access is not a first-class concept; we implement it on our side.

Effort: ~1 week for Phase 1 (login, sessions, tenant switcher, /t/:slug URLs, super-admin). SCIM and Admin Portal can come later without rework.


2. Clerk

What it is: A developer-experience-first auth platform. Originally B2C-focused; added Organizations in 2023 to compete in B2B. Excellent React SDK, lots of pre-built components (<SignIn />, <OrganizationSwitcher />, <UserButton />).

Mental model:

  • Users are top-level.
  • Organizations = tenants. Users can belong to multiple. Each membership has a role.
  • Auth methods (SSO, magic link, password, OAuth social) are enabled globally, not per-organization. Enterprise SSO is per-organization via an "Enterprise Connection" add-on.
  • UI components are drop-in: <OrganizationSwitcher /> would literally replace our Settings tenant form.

How it would work in sv0:

  1. Backend: @clerk/backend. Middleware extracts userId and orgId from the Clerk session cookie/JWT. We still keep our own users / memberships tables mirrored for queries.
  2. Frontend: wrap the app in <ClerkProvider>. Drop <SignIn />, <OrganizationSwitcher />, <UserButton /> into the layout. Use useOrganization() hook to get the current tenant slug.
  3. Super-admin: Clerk doesn't model cross-org admin. We add a role: super_admin claim on specific Clerk users (via Clerk's public metadata) and build the cross-tenant switcher ourselves (fetch /api/admin/tenants when super_admin).
  4. Per-tenant SSO: customer IT admin clicks "Add SSO" in our UI, which opens Clerk's hosted SSO configuration flow (requires the Enterprise add-on per org).

Pros:

  • Fastest time-to-first-login of any option. The React SDK is genuinely excellent.
  • <OrganizationSwitcher /> is exactly the dropdown the user asked for, for free.
  • Magic link, OAuth, password, MFA — all built in.
  • Free tier is generous for MAU; org add-ons are reasonable.

Cons:

  • Enterprise SSO connections are $75/connection/month (2-15), tiering to $60 (16-100), $30 (101-500), $15 (500+). Cheaper per-connection than WorkOS at all tiers, but requires Pro plan ($20-25/mo) + B2B add-on ($85-100/mo) + Business plan ($250/mo for SOC 2/dashboard seats) as fixed costs.
  • Clerk's session model is somewhat proprietary — migrating off is more work than WorkOS.
  • Historically B2C-first; some B2B features (SCIM, advanced org roles) are newer and less battle-tested than WorkOS.
  • The drop-in React components are opinionated about styling; theming to match our design system takes work.
  • Cross-tenant super-admin is definitely a "build it yourself" situation.
  • February 2026 pricing restructure metered enterprise connections (previously unlimited under the Enhanced Authentication add-on). Orgs with 3+ connections see increased costs vs. the old model.
  • SOC 2 artifacts now require the Business plan ($250/mo) — potentially needed for enterprise sales.

Effort: ~3-5 days for Phase 1 (thanks to pre-built components). SCIM is newer; verify it before committing.

Pricing sources: clerk.com/pricing, Feb 2026 plan changes, SuperTokens Clerk pricing analysis.


3. Stytch B2B

What it is: Stytch's B2B-specific product. Stytch started as passwordless auth and added a B2B suite in 2023 with Organizations, SSO, SCIM, and RBAC. API-first — they explicitly de-emphasize hosted UI in favor of giving you headless primitives.

Mental model:

  • Very similar to WorkOS: Organizations = tenants, Members = users within an org, Connected Apps = IdPs.
  • Every auth method (magic link, SSO, password, OAuth) can be enabled/disabled per Organization. This is more granular than WorkOS or Clerk.
  • No hosted login UI by default — you call their API and build the UI yourself. There's an optional prebuilt UI kit.

How it would work in sv0:

  1. Backend: stytch Node SDK. Custom middleware that calls stytch.sessions.authenticate() on every request, maps to our users/memberships tables.
  2. Frontend: build our own login form that calls stytch.magicLinks.email.loginOrCreate(). For SSO, call stytch.sso.start(). This is more code than Clerk or WorkOS AuthKit.
  3. Per-org auth method config: Stytch lets us toggle "this org requires SSO", "this org allows magic link only" via their dashboard or API — cleaner than WorkOS.
  4. Super-admin: similar to others — we build it on our side.

Pros:

  • The most granular per-organization auth config of the three managed options. Good for "demo tenants use magic link, enterprise tenants require SAML".
  • Free tier includes 5 SSO/SCIM connections — covers the pilot phase at zero cost.
  • API-first approach means minimal vendor lock-in on the UI layer.
  • Unlimited organizations at all tiers.

Cons:

  • SSO connections beyond 5 cost $125/connection/month — identical to WorkOS, with no published volume tiers. This is the critical finding: Stytch is not cheaper than WorkOS at scale.
  • MAU overage is $0.10/MAU — 5-8x higher than Clerk's $0.02/MRU. Not a concern at sv0's ~30 users/customer scale, but a trap if usage patterns change.
  • More code to write than Clerk (no drop-in components) or WorkOS (no AuthKit hosted flow).
  • Smaller ecosystem than WorkOS/Clerk — fewer blog posts, smaller Discord, less inertia.
  • Has an embeddable Admin Portal (updated finding) — customers can self-serve SSO/SCIM config, MFA policies, and role mapping. Less known than WorkOS's but functionally capable.
  • SCIM is included free (5 connections in free tier, shared pool with SSO). GA and supports Okta, Azure AD, OneLogin with real-time webhooks. Stronger than Clerk on this axis.
  • Pro plan ($249/mo) and Scale plan ($799/mo) include only 3 and 8 connections respectively — poor value vs WorkOS AuthKit which is free.

Effort: ~1-1.5 weeks for Phase 1. Main cost is building the login UI ourselves.

Pricing sources: stytch.com/pricing, SuperTokens Stytch pricing analysis.


4. Auth0 (Okta)

What it is: The legacy leader. Acquired by Okta in 2021. Supports everything. Used by enterprises everywhere.

Mental model:

  • Tenants in Auth0 terminology mean "instances of Auth0", not customer tenants — this is confusing. What we call a tenant is an Organization in Auth0 (added in 2021 to catch up with B2B).
  • Universal Login (hosted) handles the flow. Rules/Actions hook into the login pipeline for custom logic.
  • Enterprise Connections per Organization for SAML/OIDC.

How it would work in sv0:

  • Mechanically similar to WorkOS: Organizations map to tenants, users map to members, Universal Login handles the redirect flow. Backend verifies Auth0 JWTs (our existing JWKS middleware almost works out of the box).

Pros:

  • Everyone on the enterprise side recognizes the name — zero resistance in security reviews.
  • Feature-complete. Literally every feature any other provider has, Auth0 has.
  • Our existing JWT/JWKS middleware is closest to usable with Auth0 (least backend refactor).

Cons:

  • Pricing is brutal for B2B SaaS. Enterprise plan with Organizations starts around $240/month and scales aggressively with MAU. Not viable pre-revenue.
  • The dashboard and DX are dated compared to WorkOS/Clerk.
  • "Organizations" was bolted on in 2021 and still shows — feels like a second-class citizen.
  • Migrating off Auth0 is hard (Rules, custom claims, custom DB connections, Auth0-specific quirks).

Effort: ~1 week backend, similar to WorkOS. But the pricing makes it a non-starter unless we already sell to a customer that mandates Auth0.


5. Cloudflare Access (Zero Trust) — extend what we have

What it is: A network-layer identity gateway. Already sits in front of app.securityv0.com and dev.securityv0.com. Handles Google Workspace, GitHub, SAML, OIDC, Okta, Entra ID via Cloudflare's IdP integrations. Injects a signed Cf-Access-Jwt-Assertion header into requests reaching the origin.

Mental model:

  • CF Access policies are configured in the Cloudflare dashboard, not in app code. Policies are tied to hostnames and paths.
  • Every authenticated request gets a CF Access JWT that contains the user's email and identity provider.
  • No concept of "Organization" — CF Access doesn't know what a tenant is.

How it would work in sv0:

  1. Backend: add a middleware that verifies Cf-Access-Jwt-Assertion against CF's JWKS (well-documented), extracts email and identity_nonce, and maps that to our own users table.
  2. Tenant model: 100% our problem. CF doesn't help. We still build tenants, memberships, tenant switcher, /t/:slug URLs, per-tenant config.
  3. Per-tenant SSO: we'd create a CF Access "application" per tenant (one per subdomain or one per path pattern). Customer IdPs are configured in the CF dashboard by us, not the customer. This is the dealbreaker for self-service.
  4. Magic link: CF Access has a "One-time PIN" email method. Works fine for demos.
  5. Super-admin: we mark specific emails (e.g. @securityv0.com Google Workspace) as super-admin in our memberships table.

Pros:

  • Free for up to 50 users, then $3/user/month. Cheaper than everything else by an order of magnitude.
  • Already in place. We'd literally be connecting the dots, not adding a vendor.
  • No vendor lock-in beyond CF itself (which we already depend on).
  • Works for local dev with CF cloudflared if we want, or we just skip it locally with REQUIRE_AUTH=false.

Cons:

  • No self-service SSO onboarding. Every enterprise customer that wants to bring their Okta/Entra ID requires us to log into the CF dashboard and configure it. This scales to maybe 20 customers before it hurts. It is the single biggest argument against this option.
  • CF Access is fundamentally a hostname-scoped gateway. Multi-tenant URL patterns like /t/:slug work, but per-tenant SSO policies are cleaner with subdomains, which means wildcard TLS and wildcard CF apps — not free work.
  • No Organization/membership primitives. We build all of that.
  • Local dev story is awkward: CF Access doesn't run locally, so REQUIRE_AUTH=false stays the local dev story, and we'd diverge further between local and prod auth.
  • Audit logs and user management live in the CF dashboard, not in our app.

Effort: ~3-4 days for Phase 1 (it's mostly on our side: tenants table, memberships, switcher, /t/:slug, super-admin). But the self-service ceiling makes this a phase-1-only answer, not a long-term one.


6. Roll our own OIDC (openid-client + Mongo)

What it is: Use the openid-client npm package to implement an OIDC relying party ourselves. Store users, tenants, memberships, and per-tenant OIDC configs in Mongo. Implement magic link by generating a signed token, emailing it via Resend/Postmark, and verifying on click.

How it would work in sv0:

  1. Backend: add openid-client, iron-session (or express-session), a mail transport. Build /auth/login, /auth/callback, /auth/logout, /auth/magic-link/request, /auth/magic-link/verify. Store per-tenant OIDC config in a tenant_auth_configs collection.
  2. Frontend: build the login page, tenant-scoped callback handling, session hooks, the org switcher, the admin SSO config UI, the email templates.
  3. SCIM: we'd have to implement it. SCIM is a 400-page RFC. This alone is weeks of work.
  4. Magic link delivery: we own deliverability, bounces, rate limits, token rotation.
  5. Super-admin: easy — just a flag in our DB.

Pros:

  • Zero vendor cost.
  • Zero lock-in. It's just OIDC.
  • Complete control over the UX, data model, and session lifecycle.
  • Every feature is exactly as much or as little as we need.

Cons:

  • We become an auth company. Session rotation, CSRF, PKCE, nonce replay, clock skew, JWKS caching, SAML (if any customer wants it — SAML is not OIDC and openid-client won't help), SCIM, MFA, passkeys, password reset flows, account lockout, email deliverability, audit logs, admin portal, brute-force protection… this never ends.
  • Security risk surface is enormous. Every one of those items is a place to have a CVE.
  • Opportunity cost: the weeks spent on auth are weeks not spent on the actual product.
  • SAML support means adding @node-saml/node-saml and dealing with XML signing, which is even more painful than OIDC.

Effort: 2-3 weeks for a minimal Phase 1, probably 6-8 weeks to reach parity with what WorkOS gives us out of the box. Ongoing maintenance forever.


Side-by-side comparison

CriterionWorkOSClerkStytch B2BAuth0CF AccessRoll own
Enterprise SSO (SAML+OIDC) per tenant★★★★★★★★★★★★★★★★★★★★ (manual)★ (huge work)
Self-serve SSO onboarding (Admin Portal)★★★★★★★ (no equivalent)★★★★ (embeddable)★★★
SCIM / directory sync★★★★★★★ (not GA)★★★★ (included free)★★★★
Magic link / passwordless★★★★★★★★★★★★★★★★★★★★★★★ (build it)
B2B data model (orgs/memberships)★★★★★★★★★★★★★★★★★ (bolted on)You build it
React SDK quality★★★★★★★★★★★★★★★n/an/a
Cross-tenant super-adminDIYDIYDIYDIYDIYDIY
Pricing at 0-10 SSO customersFree (AuthKit) + $125/SSO$20/mo base + $75/SSOFree (5 SSO included)~$240/mo + SSO$0-$3/user$0 + 6wk eng
Pricing at 50 SSO customers~$5k/mo ($100/SSO tier 2)~$3.3k/mo ($60/SSO + base)~$5.6k/mo ($125/SSO, no tier)$$$$~$300/mo but ceiling reached$0 + ongoing eng
Pricing at 200 SSO customers~$10k/mo ($50/SSO tier 4)~$3.4k/mo ($15/SSO + base)No published volume tier$$$$Not viable$0 + ongoing eng
SSO cost per customer at $45k ACV16.7%→6.7% of COGS10%→2.2% of COGS16.7% of COGS (flat)N/A$0 but manual$0 but liability
Vendor lock-inLow (OIDC)MediumLowHighLowNone
Time to first login3-5 days2-3 days5-7 days5-7 days3-4 days2-3 weeks
Sellability to CISOs★★★★ ("we use WorkOS")★★★★★★★★★★★★★★★ ("CF Zero Trust")★★ ("we built it")

Recommendation: WorkOS (with active pricing management)

For a B2B security product selling to Fortune 500 CISOs, WorkOS is the right answer on technical and operational merits. However, the per-connection SSO cost requires active management — it is not a rounding error at $45k channel ACV. Reasoning:

  1. The Admin Portal is the decisive feature. Every other option forces us into a support ticket per SSO setup. WorkOS lets a customer's IT admin configure their own SAML in a 5-minute self-serve flow. At the scale we want to reach, this is the difference between auth being a non-issue and auth being a bottleneck.
  2. B2B data model is native, not bolted on. Organizations, Members, Connections, Directory Sync all map cleanly to tenants, users, memberships, tenant_auth_configs on our side.
  3. Free until real revenue. AuthKit and Magic Auth are free up to 1M MAU. SSO costs only start when enterprise contracts do.
  4. OIDC-compliant, low lock-in. If we ever need to leave (including for cost reasons), we can.
  5. CISO-friendly positioning. "We use WorkOS" is known in the security buyer community and won't raise eyebrows.
  6. The piece it doesn't solve — cross-tenant super-admin, per-tenant app config (Jira etc), /t/:slug URLs, shareable links — we have to build anyway, and that work is the same regardless of provider.

Pricing concern: At $45k channel ACV with 20% COGS target, SSO at $125/connection/month ($1,500/yr) consumes 16.7% of the COGS budget. This is not sustainable at scale without mitigation. See Cost Optimization Strategies — the highest-leverage action is a 15-minute WorkOS sales call about the startup program and volume commits.

Key insight from the deep-dive: the $125/connection price is industry-standard, not WorkOS-specific. Stytch charges the same. The only provider that is materially cheaper at scale is Clerk ($75→$15 tiering), but Clerk trades off Admin Portal maturity, session model portability, and CISO brand recognition.

Decision tree:

  1. If WorkOS startup program or volume negotiation reduces SSO to ≤$75/connection: → WorkOS. Problem solved.
  2. If WorkOS won't negotiate and we project 50+ enterprise customers within 18 months: → Switch to Clerk. Accept weaker Admin Portal; cost savings justify the ops delta.
  3. If we want zero per-connection cost and have engineering bandwidth: → WorkOS for AuthKit (free) + BoxyHQ Jackson for SAML brokering ($0 self-hosted). Best COGS but most implementation work.
  4. If budget is the overriding constraint today: → Cloudflare Access for phase 1 with a clear plan to migrate to WorkOS or Clerk when the first enterprise customer asks for Okta. Migration is viable because our users/memberships tables are provider-independent by design (ADR-016).

Immediate next step: Make the WorkOS sales call before committing to implementation.


Pricing deep-dive and COGS analysis

Updated 2026-04-10 with live pricing from all three viable providers and sv0's actual go-to-market numbers.

sv0 pricing context

ChannelACV20% COGS targetAuth budget (if 15% of COGS)
Partner (channel)$45,000/yr$9,000/yr$1,350/yr
Direct (mid)$60,000/yr$12,000/yr$1,800/yr
Direct (high)$90,000/yr$18,000/yr$2,700/yr

Sergey's constraint: 20% COGS inclusive of cloud, support, and all software licenses. Having 15%+ of that consumed by SSO alone is a scaling problem.

Detailed pricing breakdown per provider

WorkOS (current pricing as of April 2026)

ItemCostNotes
AuthKit (hosted login)Free up to 1M MAUEffectively $0 forever for sv0 (~30 users/customer × hundreds of customers ≪ 1M)
SSO connections (1-15)$125/connection/month ($1,500/yr)One connection per enterprise customer with SAML/OIDC
SSO connections (16-50)$100/connection/month ($1,200/yr)Volume tier 2
SSO connections (51-100)$75/connection/month ($900/yr)Volume tier 3
SSO connections (101-200)$50/connection/month ($600/yr)Volume tier 4
Directory Sync (SCIM)Same tiered pricing as SSOOptional, per customer
Admin PortalIncluded freeSelf-serve SAML config for customer IT admins
Magic Auth (magic link)Included free in AuthKit$0 for eval/demo customers
M2M ApplicationsIncludedNo per-app fee documented
API Keys widgetIncludedNo per-key fee documented
Startup programUnconfirmed — requires sales callPotentially waives connection fees for 12 months

WorkOS per-customer cost at sv0 scale:

ScenarioSSO customersTierAnnual cost per customerTotal annual% of COGS ($45k ACV)
Early (1-15 customers)1-15$125/mo$1,500$1,500-$22,50016.7%
Growth (16-50)30$100/mo$1,200$36,00013.3%
Scale (51-100)75$75/mo$900$67,50010.0%
Mature (101-200)150$50/mo$600$90,0006.7%

Clerk (pricing as of Feb 2026 restructuring)

ItemCostNotes
Base plan (Pro)$20/mo (annual) or $25/mo (monthly)Required for enterprise features
MRU (monthly retained users)50,000 free; $0.02/MRU overagesv0 with 30 users × 50 customers = 1,500 MRU → $0
B2B add-on (Enhanced)$85/mo (annual) or $100/moIncludes unlimited org members, domain restrictions, custom roles
Enterprise connections (2-15)$75/connection/month ($900/yr)Per SAML/OIDC connection. 1 included in Pro.
Enterprise connections (16-100)$60/connection/month ($720/yr)Volume tier 2
Enterprise connections (101-500)$30/connection/month ($360/yr)Volume tier 3
Enterprise connections (500+)$15/connection/month ($180/yr)Volume tier 4
Organizations100 free; $1/MAO overageOne org per customer tenant
Dashboard seats (4+)Requires Business plan ($250/mo)Relevant for SecurityV0 team
SOC 2 artifactsRequires Business plan ($250/mo)May be needed for enterprise sales
SCIM / Directory SyncPart of Enterprise tier or B2B add-onLess mature than WorkOS
Admin Portal equivalentExists, less battle-testedNot as polished as WorkOS
Startup programsYC, Stripe Atlas, OnDeck — up to 1yr discountsRequires application

Clerk per-customer cost at sv0 scale (assumes Pro + B2B add-on + Business plan for SOC 2):

ScenarioSSO customersConnection tierAnnual SSO cost/customerFixed annualTotal annual% of COGS ($45k ACV)
Early (1-15)10$75/mo$900~$4,260 (Pro+B2B+Biz)$13,26010.0% per customer
Growth (16-100)50$60/mo$720~$4,260$40,2608.0%
Scale (101-500)200$30/mo$360~$4,260$76,2604.0%
Mature (500+)500$15/mo$180~$4,260$94,2602.0%

Note: Fixed costs (Pro $240/yr + B2B $1,020/yr + Business $3,000/yr) amortize across customers.

Stytch B2B (current pricing)

ItemCostNotes
Free tier10,000 MAU + 5 SSO/SCIM connections + 1,000 M2M tokensGood for pilot
MAU overage$0.10/MAU beyond 10,000sv0: ~1,500 MAU → $0. At 50 customers × 30 users = still under 10K
Additional SSO connections$125/connection/month ($1,500/yr)Same price as WorkOS — no improvement
Pro plan$249/month ($2,988/yr)Includes 3 SSO connections
Scale plan$799/month ($9,588/yr)Includes 8 SSO connections
AWS Marketplace annual$25,000/yrIncludes 10K MAU + 5 SSO connections + overages
Branding removal$99/moOptional
SCIMIncluded in SSO connection pricingSame $125/connection
Admin Portal equivalentExists, less matureMore setup work per customer
M2M tokens1,000 free; $0.005/token overageRelevant for bot access

Stytch per-customer cost at sv0 scale:

ScenarioSSO customersAnnual cost/customerFixed annualTotal annual% of COGS ($45k ACV)
Early (1-5)5$0 (free tier)$0$00%
Early (6-15)10$1,500 (5 overage)$0$7,50016.7%
Growth w/ Pro plan20~$1,275*$2,988$25,50014.2%
Growth w/ Scale plan40~$1,200*$9,588$48,00013.3%

Pro/Scale include some connections, reducing marginal cost slightly. No published volume tiers beyond included connections.

Head-to-head SSO cost comparison

The metric that matters: annual cost per enterprise customer for SSO, at different scales.

Enterprise customersWorkOSClerkStytch
1$1,500$900 + base costs$0 (free tier)
5$1,500 each$900 each + ~$4.3k fixed$0 (free tier covers 5)
10$1,500 each$900 each + ~$4.3k fixed$1,500 each (beyond free 5)
15$1,500 each$900 each → $720 at 16th$1,500 each
50$1,200 each (tier 2)$720 each (tier 2)$1,500 each (no tiers)
100$900 each (tier 3)$360 each (tier 3)$1,500 each (no tiers)
200$600 each (tier 4)$180 each (tier 4)No published volume discount

Key finding: Stytch is only cheaper if you have ≤5 SSO customers (free tier). Beyond that, it's the same price as WorkOS ($125/connection) with no published volume tiers. Clerk is consistently cheaper per-connection and has the best volume curve, but has higher fixed costs and less mature B2B features.

COGS impact summary at $45k channel ACV

ScaleWorkOS annualClerk annual*Stytch annualCOGS budget ($9k/customer)
Per customer (early)$1,500 (16.7%)~$1,330 (14.8%)$1,500 (16.7%)$9,000
Per customer (50 customers)$1,200 (13.3%)~$805 (8.9%)$1,500 (16.7%)$9,000
Per customer (100 customers)$900 (10.0%)~$403 (4.5%)$1,500 (16.7%)$9,000
Per customer (200 customers)$600 (6.7%)~$201 (2.2%)$1,500 (16.7%)$9,000

Clerk: includes amortized fixed costs (Pro + B2B + Business plans).

At $60k direct ACV (COGS budget = $12k), all percentages drop by ~25%. At $90k direct ACV, by ~50%.


Auth method tiering: which clients need SSO?

Updated 2026-04-10. Not every paying customer requires a $125/mo SAML SSO connection. WorkOS AuthKit includes several free authentication methods that are fully production-ready for real clients.

Free auth methods available in WorkOS AuthKit

MethodHow it worksCostAuto-org-join?
Google OAuth"Sign in with Google" button. Works for any Google Workspace or personal Google account.$0No — requires invitation or our domain-match code
Microsoft OAuth"Sign in with Microsoft" button. Works for any Microsoft 365 or personal account.$0No — same as Google
GitHub OAuth"Sign in with GitHub". Good for developer-focused clients.$0No — same
Magic linkUser enters email, gets a one-time link.$0No — invitation-based
Email + passwordTraditional signup with email verification.$0No — invitation-based

All of these are included free in AuthKit up to 1M MAU. They are not limited to demos or evaluations — they are production-ready for paying clients.

The gap: automatic Organization membership with social login

When a user signs in via Google social login with user@acme.com, WorkOS does not automatically add them to the "Acme" Organization — even if acme.com is a verified domain on that org. Domain-based auto-join in WorkOS only triggers during SSO flows (SAML/OIDC connections).

For social-login clients, there are two approaches:

Option A: Invitation-based (zero custom code)

  1. Super-admin provisions the "Acme" tenant and verifies acme.com as a domain
  2. Super-admin invites ciso@acme.com via WorkOS → user gets email → clicks "Sign in with Google" → lands in the Acme org
  3. Acme admins can invite additional teammates through an "Invite" feature in the UI
  4. Suitable for most small-to-mid clients

Option B: Domain-match auto-join (small custom code, ~20 lines)

  1. When a user signs in via social login, our membershipMiddleware checks if their email domain matches a verified domain on any tenant
  2. If yes → auto-create a membership row → user is immediately in the right org
  3. This gives the same "just sign in and you're in" experience as SSO, without the $125/mo connection
  4. Requires a domain verification step (DNS TXT record or manual approval) to prevent spoofing

What neither option provides (and only SAML SSO does):

  • Customer IT admin enforcing login exclusively through their corporate IdP
  • Conditional access policies (require specific IP ranges, MFA, device compliance) from the customer's IdP
  • SCIM auto-provisioning (automatically add/remove users when Okta/Entra ID directory changes)
  • Centralized audit trail in the customer's own IdP dashboard

Which clients actually need SAML SSO?

Client profileTypical auth needWhy?
Small company (10-200 employees) on Google WorkspaceGoogle OAuth + invitationIT team doesn't enforce IdP-only login. "Sign in with Google" is natural.
Small company on Microsoft 365Microsoft OAuth + invitationSame — "Sign in with Microsoft" works.
Developer-focused teamGitHub OAuthNatural fit for security/devops buyers.
Mid-market (200-2000) without strict IT policySocial login + domain-match auto-joinGood enough. IT team doesn't mandate SAML.
Mid-market with IT security mandateSAML SSOIT policy requires all business tools go through Okta/Entra ID. Non-negotiable.
Enterprise (2000+) / regulated industrySAML SSO + SCIMAlways. This is a procurement checkbox.
Government / financial / healthcareSAML SSO + SCIM + MFA enforcementAlways. Compliance frameworks (FedRAMP, SOX, HIPAA) require it.

SSO adoption sensitivity analysis

We don't know what percentage of clients will require SAML SSO versus free auth. Rather than guess, the table below shows the COGS math across four adoption scenarios. Pick the row that matches your gut, or interpolate.

Assumptions: SSO = $1,500/yr (WorkOS list price, no volume discount). Non-SSO = $0. COGS budget = 20% of ACV.

SSO adoption ratePartner ($45k ACV, $9k COGS)Direct mid ($60k, $12k COGS)Direct high ($90k, $18k COGS)
35% (optimistic)$525/customer → 5.8% of COGS$525 → 4.4%$525 → 2.9%
50% (moderate)$750/customer → 8.3% of COGS$750 → 6.3%$750 → 4.2%
70% (conservative)$1,050/customer → 11.7% of COGS$1,050 → 8.8%$1,050 → 5.8%
100% (worst case)$1,500/customer → 16.7% of COGS$1,500 → 12.5%$1,500 → 8.3%

Reading the table: Even at the conservative 70% scenario, the partner-channel COGS is 11.7% — a concern but manageable with volume discounts (drops to $600/yr at WorkOS tier 4). At 50% or below, SSO COGS is under 10% across all channels. The worst-case 16.7% only materializes if literally every $45k partner client demands SAML — unlikely given the client profiles above.

With volume tier discounts (WorkOS drops to $50/connection at 101+), the cost improves further at scale. Assumes 40% SSO adoption for illustration:

Scale (all channels, 40% SSO)SSO customersNon-SSO customersBlended annual auth/customerBlended COGS % ($45k ACV)
50 total (20 SSO)20 × $1,200/yr (tier 2)30 × $0$4805.3%
100 total (40 SSO)40 × $900/yr (tier 3)60 × $0$3604.0%
200 total (80 SSO)80 × $600/yr (tier 4)120 × $0$2402.7%

Implementation note

The domain-match auto-join code (Option B above) should be included in the Phase 1 implementation plan. It's ~20 lines in membershipMiddleware:

on social-login callback:
email_domain := extract_domain(authContext.user.email)
matching_tenant := db.tenants.findOne({ verified_domains: email_domain })
if matching_tenant AND NOT existing_membership(user, matching_tenant):
db.memberships.insert({ user_id, tenant_id: matching_tenant._id, role: "member" })

This also requires adding a verified_domains: string[] field to the TenantDoc type and a small admin UI for domain verification (DNS TXT record check or manual super-admin approval).


Cost optimization strategies

Regardless of provider, there are concrete ways to reduce the per-customer auth COGS.

Strategy 1: Negotiate volume commitments

All three providers offer custom enterprise pricing. Concrete levers:

  • WorkOS startup program — unconfirmed terms but reportedly waives connection fees for 12 months. A 15-minute sales call is the highest-ROI action on this list.
  • Annual volume commit — committing to X connections/year unlocks lower per-connection rates. WorkOS tier 4 ($50/connection) is normally at 101+, but a commitment may unlock it earlier.
  • Clerk startup program — YC/Stripe Atlas partners get pre-negotiated discounts for up to 1 year. We qualify via Y Combinator or Stripe Atlas if applicable.
  • Stytch AWS Marketplace — $25k/yr flat rate includes 5 SSO connections + base features. Economical if we have exactly 5-8 enterprise customers.

Strategy 2: Defer SSO to contract signing (already planned)

SSO is only enabled when a paid enterprise contract is signed. Evaluations, POCs, and demos use free magic link. This means:

  • The first $125/mo hits the books the same day the first enterprise contract does.
  • 80%+ of active tenants may never need SSO (small teams, trials, internal).
  • The WorkOS bill scales 1:1 with enterprise revenue events, not with tenant count.

Strategy 3: Bundle SSO into the enterprise tier

If SSO costs $1,500/yr per customer, make it a line item in the enterprise pricing:

  • $45k channel ACV → SSO is "included" but the price already accounts for it (3.3% of ACV).
  • $60k+ direct ACV → SSO cost is 2.5% of ACV, well within normal software COGS.
  • Alternative: offer a "Standard" tier without SSO (magic link + password) at $30k ACV, and an "Enterprise" tier with SSO at $45k+. The $15k delta more than covers the $1,500 SSO cost.

Strategy 4: Open-source SAML proxy (hybrid approach)

Use WorkOS for everything except SSO brokering. Use an open-source SAML proxy for the actual IdP connections:

OptionWhat it isCostTrade-off
BoxyHQ SAML JacksonOSS SAML/OIDC proxy, self-hosted$0 (self-hosted) or $49/mo (cloud)We run infra, no Admin Portal, more ops per customer
SSOJetSSO-as-a-service, self-hosted optionFrom $49/moLighter than WorkOS/Clerk for SSO-only
OssoOSS SAML admin$0 (self-hosted)Less maintained, Ruby-based

Hybrid architecture: WorkOS for AuthKit (login, sessions, magic link, user management — free), BoxyHQ Jackson for SAML/OIDC brokering ($0 self-hosted). We'd lose WorkOS Admin Portal (customers configure SAML via our own UI or Jackson's admin), but eliminate the $125/connection cost entirely.

Trade-off: More engineering time (Jackson setup, SAML config UI), more ops burden (we host and maintain the proxy), less polished customer experience (no WorkOS Admin Portal). Estimated: 2-3 weeks additional implementation + ongoing maintenance. At 50 enterprise customers, this saves ~$75k/yr vs WorkOS but costs us a full-time week of ops per quarter.

Strategy 5: Switch to Clerk if volume is the priority

Clerk's aggressive volume tiers make it the cheapest at scale:

  • At 100 customers: $360/yr per customer vs WorkOS $900/yr → saves $54k/yr
  • At 200 customers: $180/yr per customer vs WorkOS $600/yr → saves $84k/yr

The trade-off is a weaker Admin Portal (more ops per onboarding) and a more proprietary session model (harder exit). If onboarding velocity matters less than COGS, Clerk wins on pure cost.

Strategy 6: Negotiate SSO into customer contracts

Enterprise customers often have their own SSO budgets. Frame it as: "SSO integration is available as part of the Enterprise tier at $X" — passing the cost through rather than absorbing it. Common in B2B SaaS where per-tenant SSO is an explicit feature, not a default.

  1. Immediate: Call WorkOS sales. Ask about startup program, volume commit pricing for 10-20 connections, and whether they can match Clerk's tier 3+ rates. This is 15 minutes of work with potentially $50k+/yr savings at scale.
  2. If WorkOS negotiation succeeds: Proceed with WorkOS per current plan. The combination of Admin Portal + negotiated rates + deferred SSO activation makes the COGS math work.
  3. If WorkOS negotiation fails and we project 50+ enterprise customers within 18 months: Switch recommendation to Clerk. Accept the weaker Admin Portal; the cost savings justify the extra ops.
  4. If we want zero per-connection cost: Evaluate BoxyHQ Jackson hybrid. Only viable if we have engineering bandwidth for the proxy setup and are willing to build our own SAML config UI.

Note: The open questions that were previously in this section have been resolved. Provider choice, phasing, admin identity source, local dev story, and per-tenant config scope are all addressed in ADR-017 and the implementation plan.