LabHub

Blog

API & Web App Auth Libraries 2026 Deep Dive — Auth.js v5 · Lucia v3 · better-auth · Clerk · Stytch · WorkOS · Kinde · SuperTokens · Frontegg

한국어English日本語

Prologue — In 2026, "Should we still build our own auth?"

In the 2010s, "build your own login screen" was the default. In the early 2020s, Auth0 and Firebase Auth pushed everyone to "outsource auth to SaaS." In 2026, we are back at the crossroads.

This article walks the whole landscape. We compare libraries vs managed vs OSS-SaaS, unpack the protocol layer (OAuth, passkeys), cover B2B requirements (SSO/SCIM/audit), and survey Korean and Japanese local ID providers. We end with a who-picks-what recommendation.


1. The 2026 Web Auth Landscape — Library vs Managed vs OSS-SaaS

Three camps.

┌──────────────────────────────────────────────────────────────────────┐
│             Three Categories of 2026 Web Auth Options                │
│                                                                      │
│  ┌────────────────┐   ┌────────────────┐   ┌────────────────────┐   │
│  │  Library       │   │  Managed SaaS  │   │  OSS-SaaS / Hybrid │   │
│  │  (DIY)         │   │  (Buy)         │   │  (Self-host OK)    │   │
│  │                │   │                │   │                    │   │
│  │ - Auth.js v5   │   │ - Clerk        │   │ - SuperTokens      │   │
│  │ - Lucia v3     │   │ - Stytch       │   │ - Logto            │   │
│  │ - better-auth  │   │ - WorkOS       │   │ - Ory Network      │   │
│  │ - iron-session │   │ - Kinde        │   │ - Keycloak Cloud   │   │
│  │ - Passport.js  │   │ - Frontegg     │   │ - Hanko Cloud      │   │
│  │ - JOSE/jose    │   │ - Auth0        │   │                    │   │
│  └────────────────┘   └────────────────┘   └────────────────────┘   │
│       ↑                     ↑                       ↑                │
│   Your DB              Their DB                 Either               │
│   Your domain          Their widgets           Usually either        │
│   $0/MAU              $25 to $2000+/M          $0 to hundreds/M      │
└──────────────────────────────────────────────────────────────────────┘

Strengths and weaknesses.

CategoryStrengthsWeaknessesBest fit
LibraryFull code control, $0 cost, you own the data100% security responsibility, time-consuming, build passkeys/SSO yourself1 to 2 senior full-stack devs, MAU under 100k, you take compliance
ManagedFast time to market, MFA/SSO/SCIM in a box, inherited SOC2Cost explodes with MAU, lock-in, domain couplingSeed to Series B startups, MAU expected to spike
OSS-SaaSSelf-host option, code visibilityOperational complexity, managed is still managed costEnterprise, data sovereignty, EU/Korean regulated industries

The 2026 trend: hybrid migrations are common. "Start with Clerk, move to better-auth after 50k MAU" is a frequent path. Migration is expensive, so the initial choice still matters a lot.


2. Auth.js v5 (formerly NextAuth.js) — The Node/Next.js De Facto Standard

Auth.js v5 is the successor to NextAuth.js. The 2024 major rebrand expanded adapters beyond Next.js to SvelteKit, SolidStart, Express, Hono, and more.

Core model

// auth.ts (Next.js App Router)
import NextAuth from 'next-auth'
import Google from 'next-auth/providers/google'
import { PrismaAdapter } from '@auth/prisma-adapter'
import { prisma } from '@/lib/prisma'

export const { auth, handlers, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [Google],
  session: { strategy: 'database' },
  callbacks: {
    async session({ session, user }) {
      session.user.id = user.id
      return session
    },
  },
})

What changed in v5 (v4 to v5)

Strengths and weaknesses


3. The Lucia v3 to better-auth Shift

Lucia v3 (author: pilcrowOnPaper) was popular in 2023 to 2024 as "a framework-agnostic minimal session library." Its core was a Lucia object + adapter + routes you wrote yourself. Almost no magic — security-sensitive teams loved it.

But in March 2025, the author announced Lucia is entering maintenance mode. The reasoning: "It belongs more as a learning resource (copy-paste) than as a library." The slot was quickly filled by better-auth.

better-auth — TypeScript-first, plugin architecture

better-auth (author: bekacru), launched in 2024, exploded in 2025. The design:

// auth.ts
import { betterAuth } from 'better-auth'
import { prismaAdapter } from 'better-auth/adapters/prisma'
import { passkey, twoFactor, organization } from 'better-auth/plugins'

export const auth = betterAuth({
  database: prismaAdapter(prisma, { provider: 'postgresql' }),
  emailAndPassword: { enabled: true },
  socialProviders: {
    google: { clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET! },
  },
  plugins: [passkey(), twoFactor(), organization()],
})

Auth.js vs better-auth

DimensionAuth.js v5better-auth
Launched2018 (NextAuth) to 2024 (v5)2024
FrameworksNext.js-first, multi-frameworkNext.js, SvelteKit, Nuxt — equal support
PasskeysBeta adapterFirst-class plugin
2FA / MFABuild yourselfPlugin
Organizations / multi-tenantBuild yourselfPlugin
Type inferenceOKStronger
MaturityHighCatching up fast

For new Next.js projects in 2026, better-auth deserves a serious look. Auth.js wins on stability and ecosystem, better-auth on feature richness and type safety.


4. Clerk — The Gold Standard of Managed UX

Clerk (founded 2021, YC W21) became the de facto standard for managed auth SaaS in 2024 to 2026. Its strengths are obvious.

Pricing (Q1 2026)

Sample code

// app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs'

export default function RootLayout({ children }) {
  return (
    <ClerkProvider>
      <html><body>{children}</body></html>
    </ClerkProvider>
  )
}

// app/sign-in/page.tsx
import { SignIn } from '@clerk/nextjs'
export default function Page() {
  return <SignIn />
}

Clerk's traps


5. Stytch — Passwordless-First, Separated B2C/B2B

Stytch (founded 2020, Series B) was the earliest to focus hard on passwordless.

B2B SaaS strengths

Stytch B2B is designed around the organization unit.

import { StytchClient } from 'stytch'

const stytch = new StytchClient({
  project_id: process.env.STYTCH_PROJECT_ID!,
  secret: process.env.STYTCH_SECRET!,
})

// Send a magic link
await stytch.magicLinks.email.loginOrCreate({
  email: 'user@acme.com',
  login_magic_link_url: 'https://app.example.com/auth/callback',
})

Pricing


6. WorkOS — Specialized in Enterprise SSO/SCIM

WorkOS positions itself as "the box that unblocks B2B SaaS moving upmarket — SSO, SCIM, and audit logs."

Pricing model

WorkOS prices differently from the rest.

A single B2B (enterprise) customer with SSO is $99/month revenue equivalent. This pricing maps to SaaS economics where one enterprise customer = average LTV of tens of thousands of dollars.

Sample code — SSO flow

import { WorkOS } from '@workos-inc/node'

const workos = new WorkOS(process.env.WORKOS_API_KEY!)

// 1) Generate login URL
const authUrl = workos.sso.getAuthorizationUrl({
  connection: 'conn_01EHWNCE74X7JSDV0X3SZ3KJNY',
  redirectUri: 'https://app.example.com/callback',
  clientId: process.env.WORKOS_CLIENT_ID!,
})

// 2) Get profile from callback
const { profile, accessToken } = await workos.sso.getProfileAndToken({
  code: searchParams.code,
  clientId: process.env.WORKOS_CLIENT_ID!,
})

7. Kinde — Full-Stack Managed, "Cheaper and Simpler Than Auth0"

Kinde (founded 2022 in Australia) aimed to "remove Auth0's complexity and price." The result is the following in one box.

Pricing

Notable: the Free plan is the most generous. 10k MAU free is the most lenient in 2026.


8. SuperTokens — OSS SaaS, Self-Host Option

SuperTokens (founded 2020, YC W21) has a dual model: open source + managed.

Pricing

Sample code

import SuperTokens from 'supertokens-node'
import Session from 'supertokens-node/recipe/session'
import ThirdPartyEmailPassword from 'supertokens-node/recipe/thirdpartyemailpassword'

SuperTokens.init({
  framework: 'express',
  supertokens: {
    connectionURI: 'http://localhost:3567', // or managed core URL
  },
  appInfo: {
    appName: 'My App',
    apiDomain: 'https://api.example.com',
    websiteDomain: 'https://example.com',
  },
  recipeList: [
    ThirdPartyEmailPassword.init({ /* providers */ }),
    Session.init(),
  ],
})

SuperTokens in one line: "When you want OSS loyalty but optional managed hosting."


9. Frontegg — Managed B2B Customer Auth

Frontegg (founded 2019 in Israel) positions itself as a full-stack solution to B2B SaaS customer auth.

It overlaps with WorkOS in positioning, but differs.


10. Hanko — Passkey-First OSS

Hanko is a Germany-based OSS project with the slogan "Kill the password." Centered on passkeys, WebAuthn, passcodes (OTP).

<script type="module" src="https://esm.sh/@teamhanko/hanko-elements/dist/elements.js"></script>
<hanko-auth api="https://your-hanko-api.example.com"></hanko-auth>

For "just ship passkeys fast," Hanko is the simplest. The catch: thinner OAuth social login coverage than other libraries.


11. Passport.js / iron-session / jose — Node Legacy + Minimal

Three classics.

// Mint and verify a JWT with jose
import { SignJWT, jwtVerify } from 'jose'

const secret = new TextEncoder().encode(process.env.JWT_SECRET!)

const token = await new SignJWT({ sub: 'user-42' })
  .setProtectedHeader({ alg: 'HS256' })
  .setExpirationTime('15m')
  .sign(secret)

const { payload } = await jwtVerify(token, secret)

These three are the "internal components" of the bigger SaaS/library packages. Fewer teams build from scratch with them, but API gateways and microservice auth still reach for them first.


12. OAuth Flows — Authorization Code with PKCE Is the Answer

In 2026, OAuth flows have settled.

┌─────────────────────────────────────────────────────────────────┐
│              2026 OAuth Flow Recommendations                    │
│                                                                 │
│  Authorization Code + PKCE      -> Web, mobile, SPA (standard)  │
│  Client Credentials              -> Server-to-server (M2M)      │
│  Device Authorization            -> TV/CLI/IoT                  │
│  Refresh Token Rotation          -> Combine with all flows      │
│  Resource Owner Password         -> Forbidden (legacy only)     │
│  Implicit Flow                   -> Deprecated, replaced by PKCE│
└─────────────────────────────────────────────────────────────────┘

OAuth 2.1 (draft, with the RFC process advancing in 2024 to 2025) formally removes Implicit and ROPC. Never use them in new code.

PKCE — Mandatory for SPA and Mobile

PKCE (Proof Key for Code Exchange, RFC 7636) solves the problem that SPAs and mobile apps cannot keep a client_secret.

  1. The client generates a code_verifier (random string).
  2. The SHA256 hash is sent to the IdP as code_challenge.
  3. The IdP issues an authorization_code.
  4. On token exchange the client sends the original code_verifier.
  5. The IdP compares the hash and then issues the access token.

This way, a man in the middle who steals the authorization_code cannot exchange it for a token. By 2026 every modern IdP/library enables this by default.


13. Passkeys / WebAuthn — The Effective Standard in 2026

By 2026, passkey adoption is past the tipping point.

Passkey mechanics in brief

  1. On registration the device generates a public/private key pair. The private key never leaves the device (Secure Enclave/TPM).
  2. The server stores only the public key.
  3. On login the server issues a challenge (random nonce). The device signs with the private key. The server verifies with the public key.
  4. iCloud Keychain / Google Password Manager sync the keys across devices.

Passkey support by library/SaaS (2026Q1)

SolutionPasskey SupportNotes
ClerkFirst-classSmoothest UI/UX
StytchFirst-classHeadless SDK
HankoFirst-class (first-mover)Passkey-centric design
better-authPluginEnable in 1 to 2 lines
SuperTokensFirst-classMost freedom when self-hosted
Auth.js v5Beta adapterSome limitations
WorkOS AuthKitFirst-classEnterprise-friendly

SimpleWebAuthn — For Hand-rolled Implementations

If you handle WebAuthn directly, SimpleWebAuthn is the de facto library in 2026. It provides both backend (@simplewebauthn/server) and browser (@simplewebauthn/browser) packages.


Magic links, OTP (SMS/email), and TOTP (authenticator apps) are password alternatives and second-factor options for MFA.

MethodSecurityUXCostBest fit
PasskeysHighest (phishing resistant)BestFreeEvery new project
TOTPHigh (offline)MediumFreeMFA
Email OTPMedium (depends on email security)MediumLowSignup, recovery
Magic linksMedium (URL theft risk)GoodLowPrimary passwordless
SMS OTPLow (SIM swap)GoodHighLast resort

Magic links must be single-use, short expiry, and IP/device-bound.

// Issue a magic link token
const token = crypto.randomBytes(32).toString('base64url')
const hash = createHash('sha256').update(token).digest('hex')

await db.magicLink.create({
  data: {
    userId: user.id,
    tokenHash: hash, // never store the raw token
    expiresAt: new Date(Date.now() + 15 * 60 * 1000), // 15 minutes
    ip: request.ip,
  },
})

const url = `https://example.com/auth/verify?token=${token}`
await sendEmail({ to: user.email, magicLinkUrl: url })

Twilio Verify — The De Facto SMS OTP

Do not roll SMS OTP from scratch. Use a managed product like Twilio Verify, Vonage, or AWS SNS. Why:

In 2026, SMS itself costs 0.01to0.01 to 0.10 per message. Traffic pumping attacks have caused multi-thousand-dollar monthly losses. Always combine OTP with rate limiting and reCAPTCHA/Turnstile.


15. Sessions vs JWT — The Right 2026 Answer

The eternal debate. The 2026 answer is clear: sessions > JWT, but use short-lived JWT as your access token.

Comparison

DimensionServer sessions (DB/Redis)JWT (stateless)
Immediate revokeYes (delete a row)No (valid until expiry)
Verify costDB/Redis round-tripJust signature verification
ScalingNeeds Redis clusterInfinite (assumes secret stays safe)
Data exposureCookie only (opaque)Payload base64 visible
RecoveryCan rotate keysRe-login after key rotation
Recommended useUser sessionsM2M, short-lived access tokens
┌─────────────────────────────────────────────────────────┐
│                  Recommended Hybrid Flow                │
│                                                         │
│  1) After login the server issues:                      │
│     - access_token (JWT, 5 to 15 min, perms in payload) │
│     - refresh_token (opaque, in DB, 7 to 30 days)       │
│                                                         │
│  2) API calls authenticate with the access_token        │
│     - Signature verification only, no DB lookup         │
│                                                         │
│  3) On access expiry, refresh to get a new one          │
│     - Verify the refresh row in DB, mint new access     │
│     - Refresh rotation — used tokens are invalidated    │
│                                                         │
│  4) On immediate logout, delete the refresh row         │
│     - Access stays valid until natural expiry           │
│     - Want faster cutoff? Keep access very short        │
└─────────────────────────────────────────────────────────┘

This pattern is OAuth 2.0's refresh token rotation. By 2026 it's the default in every modern IdP/library.


16. Token Storage — HttpOnly Cookies Are the Answer

Where to store tokens in the browser is a perennial debate.

StorageXSS-safeCSRF-safeSurvives reloadRecommendation
HttpOnly + Secure + SameSite=Lax cookieSafeMostly safeYesUser sessions
localStorageRisky (JS access)Safe (no auto-send)YesAvoid
sessionStorageRiskySafeLost on tab closeAvoid
In-memory variableSafeSafeLost on reloadAccess token only

CSRF defense: SameSite=Lax/Strict + state token or double-submit cookie. SameSite alone is not a complete CSRF defense (same-site subdomain attacks, GET state changes, etc.).


17. OWASP A07 — Top 5 Authentication Failure Traps

OWASP Top 10 2021 lists A07: Identification and Authentication Failures. Still alive in 2026.

1) Missing brute-force protection

2) Account enumeration

3) Weak password policy

4) Session fixation

5) Insecure password storage


18. B2B Auth Requirements — SSO / SCIM / Audit / IP / MFA Enforcement

B2B SaaS chasing enterprise customers needs five things, almost mandatory.

  1. SSO (SAML 2.0 + OIDC) — connect to Okta, Microsoft Entra, Google Workspace, etc.
  2. SCIM (System for Cross-domain Identity Management) — provisioning/deprovisioning in the customer's IdP propagates automatically.
  3. Audit logs — who did what when. SOC2, ISO 27001, HIPAA requirements.
  4. IP allowlist / denylist — restrict login to certain IP ranges.
  5. MFA enforcement — organization-level "MFA is required" policy.

"Enterprise auth tax"

The B2B SaaS industry has a joke: "Add enterprise SSO and the price goes up 10x." Why:

If you build it yourself, boxyhq/saml-jackson or SuperTokens multi-tenant mode are worth looking at.


19. Korean Authentication — NAVER · Kakao · PASS · KakaoTalk Certificate

Auth flows specific to the Korean market.

Add NAVER to Auth.js

// auth.ts
import Naver from 'next-auth/providers/naver'

export const { auth } = NextAuth({
  providers: [
    Naver({
      clientId: process.env.NAVER_CLIENT_ID!,
      clientSecret: process.env.NAVER_CLIENT_SECRET!,
    }),
  ],
})

Kakao follows the same pattern. Both are nearly mandatory if Korean users are a primary target.


20. Japanese Authentication — LINE · Yahoo!Japan · Mercari · d ACCOUNT

Japan-market specifics.

Add LINE Login

Auth.js has a LINE provider. Services with heavy Japanese user share (especially e-commerce, food delivery, gaming) treat LINE as their primary option as standard.


21. Bot Defense — Turnstile · hCaptcha · reCAPTCHA Enterprise · Arkose

CAPTCHA in 2026 has evolved to be nearly invisible.

Cloudflare Turnstile side by side

<form action="/login" method="POST">
  <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
  <button type="submit">Sign in</button>
</form>
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

Server verification.

const response = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
  method: 'POST',
  body: new URLSearchParams({
    secret: process.env.TURNSTILE_SECRET!,
    response: token,
    remoteip: clientIp,
  }),
})

For new projects in 2026, start with Turnstile. It's free and the UX is the smoothest.


22. Bot Defense in the AI Era — Passive Signals + Behavioral Analysis

LLMs caused an explosion of automated attacks. 2026 bot defense combines:

Castle, Sift, Stytch Fraud & Risk, Arkose Bot Manager, and similar managed providers fill this space. Building it yourself is extremely hard.


23. Migration Scenarios — Clerk → Auth.js, Auth0 → Stytch

Moving from managed to library (or between managed providers) is common.

Clerk → Auth.js + Postgres

  1. Export users (JSON) from the Clerk Admin Dashboard.
  2. Create users, accounts, sessions tables in Postgres and import.
  3. Password hash migration is not possible — Clerk does not hand over its hashes. Two options:
    • Option A: send "Reset your password" emails to every user.
    • Option B: drop password auth — only allow magic links and OAuth.
  4. Re-map OAuth accounts via providerAccountId in the accounts table.
  5. Invalidate active sessions — everyone re-logs in.

Auth0 → Stytch

Auth0 lets you export password hashes (bcrypt). Stytch accepts bcrypt hash import, so passwords migrate as-is.

See Stytch Migration Docs.

Key rotation and gradual migration

Large services use a dual-issuance window.


24. Who Picks What

Decision tree.

START
  ├─ MVP / side project / MAU < 10,000?
  │     YES -> Auth.js v5 or Clerk Free
  │            (Next.js -> consider better-auth)
  ├─ Large B2C (MAU 100k+) and managed is OK?
  │     YES -> Clerk or Stytch
  │     (Run a pricing simulation first)
  ├─ B2B SaaS that needs enterprise SSO?
  │     YES -> WorkOS (SSO/SCIM)
  │           + your own auth (Auth.js / better-auth)
  │           or Stytch B2B / Frontegg integration
  ├─ Data sovereignty / self-host required?
  │     YES -> SuperTokens (self-hosted)
  │           or Logto, Ory Network (separate post)
  ├─ Passkey-first, kill the password?
  │     YES -> Hanko or Clerk
  ├─ Minimal / code visibility / fewest deps?
  │     YES -> iron-session + jose assembled by hand
  └─ Heavy Korean / Japanese user share?
        YES -> Pick one above + add NAVER/Kakao (KR)
              or LINE/Yahoo!JP (JP) provider manually

Epilogue — The Next Decision Point for 2026 Auth

Three big takeaways.

  1. Passkeys are no longer optional. A new 2026 project shipping without passkeys starts in security debt. Whether you choose Clerk, Stytch, Hanko, or better-auth, turn passkeys on.
  2. Simulate MAU pricing. Clerk/Stytch/Auth0's 25to25 to 99/month is the starting point. Model the bill at 100k MAU and plan migration around 50k MAU. That's the safe move.
  3. Look at SSO layers like WorkOS early when going B2B. When an enterprise customer asks for SSO, building from scratch eats 2 to 4 weeks in SAML debugging. Pre-paving is cheaper.

"Choosing an auth library/SaaS decides 6 months of fast shipping and 5 years of operating cost at the same time. Look beyond the fast start to the migration cost."

Among managed options, data portability (especially password hash export) decides your 5-year freedom. Treat auth as an infrastructure decision — as heavy as your database choice.


References

Comments

No comments yet.

Sign in to leave a comment