Clerk vs Auth0 vs WorkOS for B2B SaaS
TL;DR
Clerk, Auth0, and WorkOS solve different stages of the same problem. Clerk is the fastest to implement and best for early-stage SaaS (free up to 10,000 MAU). Auth0 is the enterprise workhorse with 30+ years of battle-testing and every enterprise feature you'll need eventually. WorkOS is the specialist — purpose-built to add enterprise SSO (SAML/OIDC), SCIM provisioning, and audit logs to an existing product. For most boilerplates, the path is: Clerk to launch → WorkOS when enterprise customers demand SSO.
Key Takeaways
- Clerk: best DX, fastest setup, built for Next.js App Router — free to 10K MAU then $0.02/MAU
- Auth0: most feature-complete, best enterprise support, complex pricing — $23/month to start
- WorkOS: not a full auth provider — adds enterprise SSO/SCIM/audit logs on top of existing auth
- Supabase Auth: free, self-contained, best for Supabase-native boilerplates
- Migration difficulty: Clerk → WorkOS is a natural path; Auth0 → anything is painful (vendor lock-in)
- B2B trigger point: when your first enterprise customer asks for SSO, you need WorkOS or Auth0
The Auth Provider Landscape
Full Auth Providers (replace your auth completely):
Clerk — Developer-first, Next.js-optimized
Auth0 — Enterprise-grade, 30+ years legacy
Supabase — Self-contained, free, Postgres-native
NextAuth — Open source, self-hosted, most flexible
Enterprise Auth Add-ons (work alongside your auth):
WorkOS — SSO + SCIM + Directory Sync + Audit Logs
Okta — Enterprise SSO and Identity Management
When to use each:
Early stage (<10K MAU, B2C-ish) → Clerk
Enterprise from day 1 → Auth0 or WorkOS
Supabase stack → Supabase Auth
Privacy / self-host → NextAuth
Adding SSO to existing product → WorkOS
Clerk — The Developer-First Default
Price: Free (10,000 MAU) → $0.02/MAU after, $25/month for organizations Stack support: Next.js, React, Remix, Astro, and more GitHub stars: N/A (closed source) Best for: indie hackers, early-stage B2C and light B2B SaaS
Clerk's key advantage is the tightest Next.js App Router integration of any auth provider:
// Clerk setup in Next.js (Next.js App Router):
// middleware.ts — protect routes:
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isProtectedRoute = createRouteMatcher([
'/dashboard(.*)',
'/api/protected(.*)',
]);
export default clerkMiddleware(async (auth, req) => {
if (isProtectedRoute(req)) {
await auth.protect();
}
});
export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};
// Server components (zero boilerplate):
import { currentUser, auth } from '@clerk/nextjs/server';
export default async function DashboardPage() {
const user = await currentUser();
const { userId, orgId, orgRole } = await auth();
return (
<div>
<p>Hello, {user?.firstName}!</p>
{orgId && <p>Organization: {orgId}</p>}
</div>
);
}
// Client components:
import { useUser, useOrganization } from '@clerk/nextjs';
export function UserProfile() {
const { user, isLoaded } = useUser();
const { organization } = useOrganization();
if (!isLoaded) return <div>Loading...</div>;
return (
<div>
<p>{user?.emailAddresses[0]?.emailAddress}</p>
{organization && <p>Team: {organization.name}</p>}
</div>
);
}
Clerk features:
- Email/password, magic links, OAuth (Google, GitHub, Apple, etc.)
- Passkeys (WebAuthn) — passwordless biometric auth
- Organizations and teams (multi-tenancy built-in)
- Role-based access control (RBAC)
- Pre-built UI components (sign-in, sign-up, profile, org management)
- User management dashboard (no-code admin)
- JWT templates (add custom claims for Supabase RLS, Hasura, etc.)
- SSO via SAML/OIDC (Organizations add-on: $25/org/month)
Clerk limitations:
- SSO costs extra ($25/org/month) — can get expensive at scale
- Can't fully self-host (hosted auth pages on
accounts.clerk.dev) - Pricing gets steep at enterprise scale (10K+ organizations)
- Less customizable UI than building your own
Clerk is right for:
- Next.js developers who want auth solved in under an hour
- B2C SaaS with optional team features
- Early B2B SaaS that may not need SSO for years
- Indie hackers and small dev teams
Auth0 — The Enterprise Workhorse
Price: Free (7,500 MAU, no organizations) → $23/month Essential → custom enterprise Stack support: Any framework, any language By: Okta (acquired 2021) Best for: teams expecting enterprise customers from day one
Auth0 has the most features of any auth provider but also the steepest learning curve:
// Auth0 with Next.js (App Router):
// app/api/auth/[auth0]/route.ts
import { handleAuth } from '@auth0/nextjs-auth0';
export const GET = handleAuth();
// middleware.ts:
import { withMiddlewareAuthRequired } from '@auth0/nextjs-auth0/edge';
export default withMiddlewareAuthRequired({
returnTo: '/',
});
export const config = {
matcher: '/dashboard/:path*',
};
// Server component:
import { getSession } from '@auth0/nextjs-auth0';
export default async function DashboardPage() {
const session = await getSession();
if (!session) redirect('/api/auth/login');
return <Dashboard user={session.user} />;
}
// Client component:
import { useUser } from '@auth0/nextjs-auth0/client';
export function Profile() {
const { user, error, isLoading } = useUser();
if (isLoading) return <div>Loading...</div>;
if (error) return <div>{error.message}</div>;
return user ? (
<div>
<img src={user.picture ?? ''} alt={user.name ?? ''} />
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
) : (
<a href="/api/auth/login">Login</a>
);
}
Auth0's enterprise features (the reason it exists):
- Universal Login — customizable hosted login page
- Organizations — multi-tenancy with per-org policies
- Enterprise Connections — SAML, WS-Federation, OIDC, LDAP
- SCIM provisioning — auto-provision users from enterprise IdPs
- MFA — TOTP, SMS, push notifications, WebAuthn
- Attack protection — brute force, breach detection, suspicious IP
- Anomaly detection — ML-based suspicious activity detection
- Fine-grained authorization (FGA) — relationship-based access control
- Log streams — export auth events to your SIEM
- Custom domains —
auth.yourdomain.com
Auth0 pricing reality:
Free: 7,500 MAU, 2 social providers, no organizations
Essential: $23/month — still limited (no custom domains, limited enterprise features)
Professional: $240/month — 1,000 organizations included
Enterprise: Custom — SSO, SCIM, SLA, dedicated support
The catch: enterprise features require enterprise pricing. You can't add SAML SSO on the $23/month plan. Many teams start on Auth0, discover they need SSO at scale, and find themselves on $500+/month plans.
Auth0 is right for:
- Teams expecting enterprise sales from day one
- Companies with compliance requirements (SOC2, HIPAA, FedRAMP)
- Multi-language or multi-framework apps (Auth0 has SDKs for everything)
- Teams who need SAML SSO, SCIM, audit logs immediately
Auth0 watch-out: the migration off Auth0 is painful. User passwords are hashed with Auth0's key — you can't export them. Plan your exit strategy before going in.
WorkOS — The Enterprise Add-On
Price: Free (1M MAU for SSO) → $125/month for Audit Logs/SCIM By: WorkOS (YC-funded, founded by ex-Stripe Michael Grinich) Best for: adding enterprise features to an existing SaaS product
WorkOS is fundamentally different from Clerk and Auth0. It's not a full auth provider — it handles the enterprise-specific features (SSO, SCIM, Directory Sync, Audit Logs) while you keep your existing auth for regular users.
// WorkOS for SSO — your flow:
// 1. Regular users: still use Clerk/Auth0/Supabase Auth
// 2. Enterprise users: redirect through WorkOS for SSO
// app/api/auth/sso/route.ts
import WorkOS from '@workos-inc/node';
const workos = new WorkOS(process.env.WORKOS_API_KEY!);
// Step 1: Get authorization URL from WorkOS:
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const organizationId = searchParams.get('org')!;
const authorizationUrl = workos.sso.getAuthorizationUrl({
organization: organizationId,
redirectUri: `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/sso/callback`,
clientId: process.env.WORKOS_CLIENT_ID!,
});
return Response.redirect(authorizationUrl);
}
// Step 2: Handle SSO callback:
// app/api/auth/sso/callback/route.ts
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const code = searchParams.get('code')!;
// Exchange code for user profile:
const { profile } = await workos.sso.getProfileAndToken({
code,
clientId: process.env.WORKOS_CLIENT_ID!,
});
// profile.email, profile.firstName, profile.organizationId
// Now create or find user in YOUR database:
const user = await findOrCreateUser({
email: profile.email,
name: `${profile.firstName} ${profile.lastName}`,
workosProfileId: profile.id,
organizationId: profile.organizationId,
});
// Create your session (your auth system):
await setSession(user.id);
return Response.redirect('/dashboard');
}
WorkOS features:
- SSO: SAML 2.0, OIDC — connect to Okta, Azure AD, Google Workspace, OneLogin, etc.
- Directory Sync (SCIM): auto-provision/deprovision users from enterprise IdP
- Admin Portal: no-code portal where enterprise IT admins configure SSO
- Audit Logs: structured log of all user actions (required for enterprise compliance)
- User Management: lightweight user directory (can replace your auth for enterprise)
- Magic Auth: passwordless login via email (alternative to SSO for smaller teams)
The WorkOS Admin Portal — why it matters:
// Generate Admin Portal link for enterprise customer's IT admin:
const { link } = await workos.portal.generateLink({
organization: 'org_customer_id',
intent: 'sso', // or 'dsync' for SCIM
returnUrl: 'https://app.yourdomain.com/settings/sso',
defaultReturnUrl: 'https://app.yourdomain.com/settings',
});
// Send this link to the enterprise IT admin.
// They set up SSO without any engineering involvement.
// WorkOS guides them through Okta/Azure AD config step by step.
This is WorkOS's killer feature: enterprise IT admins can configure SSO themselves. No Zoom calls, no back-and-forth — your customer's IT department just follows the wizard.
WorkOS SCIM (auto-provisioning):
// Handle SCIM webhook from WorkOS:
// When enterprise adds user in Okta → WorkOS fires webhook → you create user
export async function POST(req: Request) {
const event = await req.json();
switch (event.event) {
case 'dsync.user.created':
await db.user.create({
data: {
email: event.data.emails[0].value,
firstName: event.data.name?.givenName,
lastName: event.data.name?.familyName,
organizationId: event.data.organizationId,
},
});
break;
case 'dsync.user.deleted':
await db.user.update({
where: { workosUserId: event.data.id },
data: { deactivatedAt: new Date() },
});
break;
}
}
WorkOS is right for:
- SaaS products adding enterprise sales to an existing B2C/SMB product
- Teams that already have auth (Clerk, Supabase, etc.) and need to add enterprise features
- Products where SSO is a blocker for large deals (common in B2B SaaS)
- Avoiding Auth0's complexity for 90% of users while serving enterprise needs
Side-by-Side Comparison
| Feature | Clerk | Auth0 | WorkOS |
|---|---|---|---|
| Type | Full auth | Full auth | Enterprise add-on |
| Free tier | 10,000 MAU | 7,500 MAU | 1M MAU (SSO) |
| Paid starts | $0.02/MAU | $23/month | $125/month |
| Next.js DX | 🏆 Best | Good | N/A (add-on) |
| SSO (SAML/OIDC) | +$25/org/month | Enterprise plan | ✅ Included |
| SCIM provisioning | +$25/org/month | Enterprise plan | ✅ Included |
| Audit logs | ❌ | Enterprise plan | ✅ Included |
| Admin portal | Limited | Limited | ✅ Self-service |
| Multi-tenancy | ✅ Built-in | Add-on | ✅ Built-in |
| Custom domain | ✅ | Pro+ plan | N/A |
| Setup time | < 1 hour | 2-4 hours | 1-2 hours (SSO only) |
| Migration pain | Low | High | N/A |
The Recommended Path
Stage 1: Pre-launch to first 1,000 users → Clerk — get auth done in an afternoon, free up to 10K MAU
Stage 2: 1,000 to 10,000 users, some B2B customers → Clerk + WorkOS — Clerk for regular auth, WorkOS when first enterprise customer asks for SSO
Stage 3: Enterprise-first from day one → Auth0 — if compliance and enterprise contracts are your primary market from the start
Cost at 5,000 users, 50 organizations:
Clerk: $25/month (Organizations plan) × 50 orgs = $100-200/month
Auth0: $240/month (Professional, includes organizations)
WorkOS: $0 for SSO, $125/month if you need Audit Logs
Clerk + WorkOS (most common path):
Clerk: $50/month (~5,000 MAU)
WorkOS: $0 (SSO free up to 1M MAU)
Total: $50/month — much cheaper
Compare boilerplates by their auth provider integrations at StarterPick.