Side-by-side comparison of 7 authentication services. Free tiers, SSO, MFA, social login, passwordless, and real code examples.
The typical OAuth/OIDC authentication flow
Why developers need authentication APIs
User signup, login, password reset, email verification. Social login (Google, GitHub, Apple). Team/org management with role-based access.
SAML/OIDC SSO for enterprise customers. Directory sync with Active Directory, Okta, Google Workspace. SCIM provisioning and audit logs.
Guest checkout with optional account creation. Passwordless login via magic links. Social login to reduce cart abandonment. Address book and order history.
Biometric authentication (Touch ID, Face ID). Phone number login with OTP. Apple/Google Sign-In. Secure token storage and refresh.
API key management for developer access. Machine-to-machine (M2M) auth with client credentials. Rate limiting per API key. Usage tracking and billing.
Anonymous auth for instant play. Link social accounts later. Cross-platform identity. Progressive profile building without friction.
Side-by-side comparison of authentication services
| Feature | Auth0 | Clerk | Firebase Auth | Supabase Auth | Keycloak | WorkOS | Stytch |
|---|---|---|---|---|---|---|---|
| Free Tier | 25K MAU | 10K MAU | 10K MAU | Unlimited | Unlimited (OSS) | 1M MAU | 25 orgs |
| Paid From | $35/mo | $25/mo | Pay-as-you-go | $25/mo | Free (self-host) | $125/SSO conn | Custom |
| Social Login | ✅ 70+ providers | ✅ 20+ providers | ✅ 12 providers | ✅ 18+ providers | ✅ Configurable | ✅ Google/Microsoft/GitHub | ✅ 10+ providers |
| Email/Password | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Magic Links | ✅ | ✅ | ✅ | ✅ | 🟡 Plugin | ✅ | ✅ |
| Phone/SMS OTP | ✅ | ✅ | ✅ (paid) | ✅ | 🟡 Plugin | ❌ | ✅ |
| MFA/2FA | ✅ TOTP + SMS + WebAuthn | ✅ TOTP + SMS + Backup | ✅ Phone + TOTP | ✅ TOTP | ✅ TOTP + WebAuthn | ✅ via partner | ✅ TOTP + SMS + WebAuthn |
| Passkeys/WebAuthn | ✅ | ✅ | 🟡 Limited | ❌ | ✅ | ❌ | ✅ |
| SAML SSO | ✅ | ✅ (Enterprise) | ✅ (Identity Platform) | ✅ (Pro) | ✅ | ✅ (Core feature) | ✅ |
| RBAC | ✅ Advanced | ✅ Roles + Permissions | 🟡 Custom claims | ✅ RLS policies | ✅ Advanced | ✅ FGA | ✅ RBAC |
| Pre-built UI | ✅ Universal Login | ✅ Components | ✅ FirebaseUI | ✅ Auth UI | ✅ Login themes | 🟡 AuthKit | ✅ UI Components |
| User Management | ✅ Dashboard | ✅ Dashboard | ✅ Console | ✅ Dashboard | ✅ Admin Console | 🟡 API only | ✅ Dashboard |
| Self-Hostable | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| Open Source | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
| M2M Auth | ✅ Client Credentials | ❌ | 🟡 Service accounts | ✅ Service role | ✅ Client Credentials | ❌ | ✅ M2M tokens |
Detailed breakdown of each authentication service
When to self-host vs when to use a managed service
| Factor | Self-Hosted (Keycloak, Supabase) | Managed (Auth0, Clerk, WorkOS) |
|---|---|---|
| Cost at Scale | ✅ Server costs only ($20-100/mo) | ❌ Per-MAU pricing ($100-1000+/mo) |
| Setup Time | ❌ Hours to days | ✅ Minutes to hours |
| Maintenance | ❌ You handle updates, security patches | ✅ Fully managed |
| Data Control | ✅ Full control, on your servers | 🟡 Provider controls data |
| Compliance | ✅ Any region, any requirement | 🟡 Limited to provider's regions |
| Uptime | 🟡 You ensure availability | ✅ 99.99% SLA typical |
| Features | 🟡 Community-driven additions | ✅ Continuously updated |
Get started with each authentication provider
// Install: npm install @auth0/nextjs-auth0
// pages/api/auth/[...auth0].js
import { handleAuth } from '@auth0/nextjs-auth0';
export default handleAuth();
// pages/_app.js
import { UserProvider } from '@auth0/nextjs-auth0/client';
export default function App({ Component, pageProps }) {
return (
<UserProvider>
<Component {...pageProps} />
</UserProvider>
);
}
// Any page - check auth
import { useUser } from '@auth0/nextjs-auth0/client';
export default function Profile() {
const { user, isLoading } = useUser();
if (isLoading) return <div>Loading...</div>;
if (!user) return <a href="/api/auth/login">Login</a>;
return <div>Welcome {user.name}!</div>;
}
// Install: npm install @clerk/nextjs
// middleware.ts
import { clerkMiddleware } from '@clerk/nextjs/server';
export default clerkMiddleware();
// app/layout.tsx
import { ClerkProvider, SignInButton, UserButton }
from '@clerk/nextjs';
export default function Layout({ children }) {
return (
<ClerkProvider>
<header>
<SignInButton />
<UserButton />
</header>
{children}
</ClerkProvider>
);
}
// Protect a page
import { auth } from '@clerk/nextjs/server';
export default async function Dashboard() {
const { userId } = await auth();
if (!userId) redirect('/sign-in');
return <div>Protected content</div>;
}
// Install: npm install firebase
import { initializeApp } from 'firebase/app';
import {
getAuth, createUserWithEmailAndPassword,
signInWithEmailAndPassword, signInWithPopup,
GoogleAuthProvider
} from 'firebase/auth';
const app = initializeApp({
apiKey: "your-api-key",
authDomain: "your-project.firebaseapp.com",
projectId: "your-project"
});
const auth = getAuth(app);
// Sign up with email
const { user } = await createUserWithEmailAndPassword(
auth, "user@example.com", "password123"
);
// Sign in with Google
const result = await signInWithPopup(
auth, new GoogleAuthProvider()
);
console.log(result.user.displayName);
// Install: npm install @supabase/supabase-js
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
'https://your-project.supabase.co',
'your-anon-key'
);
// Sign up with email
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'password123'
});
// Sign in with Google
const { data } = await supabase.auth.signInWithOAuth({
provider: 'google'
});
// Get current user
const { data: { user } } = await supabase.auth.getUser();
// Protected query with RLS
const { data: posts } = await supabase
.from('posts')
.select('*');
// Only returns rows the user has access to!
// Auth0 handles social login through Universal Login
// Just configure Google in your Auth0 dashboard
// Then redirect to login:
// Frontend - redirect to Auth0
window.location.href = `https://YOUR_DOMAIN.auth0.com/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=http://localhost:3000/callback&
scope=openid profile email&
connection=google-oauth2`;
// Backend - exchange code for tokens
const response = await fetch('https://YOUR_DOMAIN.auth0.com/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
code: authorizationCode,
redirect_uri: 'http://localhost:3000/callback'
})
});
# Start Keycloak with Docker
docker run -p 8080:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest start-dev
# Configure Google IdP in admin console:
# 1. Go to http://localhost:8080/admin
# 2. Identity Providers > Google
# 3. Add Client ID and Secret from Google Console
# Use Keycloak JS adapter in frontend:
import Keycloak from 'keycloak-js';
const keycloak = new Keycloak({
url: 'http://localhost:8080',
realm: 'my-realm',
clientId: 'my-app'
});
await keycloak.init({ onLoad: 'login-required' });
console.log('Authenticated:', keycloak.authenticated);
console.log('User:', keycloak.tokenParsed.preferred_username);
# Step 1: Redirect user to Google's OAuth consent screen
# (This happens in the browser, not cURL)
# https://accounts.google.com/o/oauth2/v2/auth?
# client_id=YOUR_CLIENT_ID&
# redirect_uri=http://localhost:3000/callback&
# response_type=code&
# scope=openid+email+profile
# Step 2: Exchange authorization code for tokens
curl -X POST https://oauth2.googleapis.com/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "code=AUTHORIZATION_CODE" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "redirect_uri=http://localhost:3000/callback" \
-d "grant_type=authorization_code"
# Step 3: Get user info with access token
curl https://www.googleapis.com/oauth2/v2/userinfo \
-H "Authorization: Bearer ACCESS_TOKEN"
# Response: {"id":"...","email":"user@gmail.com","name":"..."}
What you'll pay as your user base grows
| MAU | Auth0 | Clerk | Firebase Auth | Supabase | Keycloak | WorkOS |
|---|---|---|---|---|---|---|
| 1K | Free | Free | Free | Free | Free (server cost) | Free |
| 10K | Free | Free | Free | Free | ~$20/mo (server) | Free |
| 25K | Free | $25/mo | $75/mo | $25/mo (Pro) | ~$40/mo (server) | Free |
| 50K | $240/mo | $99/mo | $200/mo | $25/mo (Pro) | ~$60/mo (server) | Free |
| 100K | $540/mo | $249/mo | $450/mo | $25/mo (Pro) | ~$100/mo (server) | Free |
| 500K | $2,700/mo | Custom | $2,450/mo | $25/mo (Pro) | ~$200/mo (server) | Free |
| + 10 SSO | +$130/mo | +Custom | +$0.015/MAU | +$0 | +$0 | +$1,250/mo |
Prices approximate. SSO pricing is for enterprise SAML/OIDC connections. Server costs for Keycloak assume cloud VPS. Check provider websites for current pricing.
Quick decision guide based on your situation
Need quick setup, beautiful login pages, social login, and good DX. Growing user base but not enterprise yet.
Enterprise customers need SSO (SAML/OIDC), directory sync, and audit logs. Per-connection pricing makes sense.
Need native SDKs, phone auth, anonymous auth for onboarding, and integration with cloud backend.
Need unlimited users without per-MAU costs. Want database integration and self-hosting option.
Strict data residency requirements, need to run auth on your own infrastructure, enterprise IAM features.
Want to eliminate passwords entirely. Need magic links, passkeys, biometrics, and fraud detection.
Frostbyte API Gateway handles API key management, rate limiting, and usage tracking. 50 free requests/day, no signup required.
Try Frostbyte API →