I am a...
Learn more
How it worksPricingFAQ
Account
May 14, 2026 · 9 min read · Cadence Editorial

How to implement authentication in 2026 (without building it yourself)

implement authentication 2026 — How to implement authentication in 2026 (without building it yourself)
Photo by [Markus Spiske](https://www.pexels.com/@markusspiske) on [Pexels](https://www.pexels.com/photo/laptop-screen-in-close-up-shot-8247921/)

How to implement authentication in 2026 (without building it yourself)

To implement authentication in 2026, do not build it yourself. Pick a managed provider that matches your product shape (Clerk for B2C polish, Auth0 for enterprise compliance, WorkOS for B2B SSO, Better Auth if you must own the data), then ship the standard pattern: an httpOnly cookie session, middleware-checked routes, role and permission split, passkey-first login, and MFA enforced on admin paths.

That is the whole post in 80 words. Everything below is the playbook for getting it right.

The 2026 default: managed provider, not custom code

Custom auth almost always loses. The math has shifted hard in the last three years: provider quality is the highest it has ever been, free tiers are generous, and a single missed CVE costs more than five years of Auth0 bills. If you are building a public product, you are paying a managed provider. The only question is which one.

The honest counterargument is that auth code "looks easy." A bcrypt.hash, a JWT signed with a secret, a cookie. Six hours and you ship. The reason every senior engineer who has done this twice now picks a provider is that the work is not the happy path. It is account recovery, email enumeration mitigation, MFA fallback, audit logs, suspicious-login detection, SCIM provisioning, regional data residency, breached-password screening, and the four-week scramble when SOC 2 asks for a session-revocation report. Providers ship that for $25/month.

Pick your provider by product shape

The choice in 2026 is mostly settled. Match the provider to what you are building, not to a Twitter argument.

ProviderBest forFree tierStandout strength
ClerkB2C SaaS, Next.js, indie10K MAU freePre-built React components, fastest DX
Auth0Enterprise, regulated, legacy SAML25K MAU freeCompliance certifications, broadest IDP support
WorkOSB2B SaaS adding SSO + SCIMSSO + Directory Sync free to 1M MAUEnterprise auth without the procurement loop
Better AuthTeams that must own the databaseOpen sourceTypeScript-native, framework-agnostic
Supabase AuthApps already on SupabaseFree with projectRLS-native, no extra vendor

Three quick decision rules. If you are a B2C SaaS or a Next.js side project, default to Clerk. We have a longer breakdown in our Clerk review and a head-to-head with Auth0 and NextAuth that gets into the gotchas. If your buyer is an IT admin who will ask for SAML and SCIM, you want WorkOS bolted on or Auth0 from day one (we wrote up the Auth0 vs Cognito tradeoff for AWS shops). If you cannot send user data to a third party for regulatory reasons, Better Auth (the production rename of Lucia v3) is the cleanest open-source path.

The cost question is the part everyone gets wrong, so we did the math in the cost to add user authentication. Spoiler: under 50K MAU, every option is rounding-error money compared to the engineering hours custom auth burns.

The standard 2026 implementation pattern

Whatever provider you pick, the integration shape is the same. Five components, in order.

1. OAuth flow with cookie session, not raw JWT

The 2026 default is server-issued sessions stored in an httpOnly, Secure, SameSite=Lax cookie. The provider handles the OAuth handshake (PKCE for SPAs, authorization code for server apps), then sets a session cookie scoped to your domain. JWTs still exist inside the system, but they live server-side or inside the cookie, never in localStorage.

The reason is simple: a token in localStorage is readable by every script on the page, including the analytics tag your marketing team added last week. One XSS bug and your entire user base is compromised. An httpOnly cookie cannot be read by JavaScript at all. Every modern provider defaults to this. Do not override it.

The exception is non-cookie clients (mobile native, CLI). For those, store the refresh token in the OS keychain (iOS Keychain, Android Keystore, keytar on desktop), not in app preferences.

2. Middleware-based auth check

Auth lives at the edge of your request pipeline, not inside route handlers. In Next.js, that is middleware.ts. In Express, it is an app.use. In Hono, it is a c.use. The middleware reads the session cookie, validates it with the provider, attaches the user to the request, and either passes through or redirects.

A working Clerk middleware in Next.js 15:

import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'

const isProtectedRoute = createRouteMatcher(['/dashboard(.*)', '/api/private(.*)'])
const isAdminRoute = createRouteMatcher(['/admin(.*)'])

export default clerkMiddleware(async (auth, req) => {
  if (isProtectedRoute(req)) await auth.protect()
  if (isAdminRoute(req)) {
    await auth.protect((has) => has({ role: 'admin' }))
  }
})

export const config = {
  matcher: ['/((?!_next|.*\\..*).*)', '/(api|trpc)(.*)'],
}

Twelve lines. The same shape works for Auth0 (withMiddlewareAuthRequired), Better Auth (auth.api.getSession), or WorkOS (authkitMiddleware).

3. Role and permission split

Roles answer "who is this person." Permissions answer "what can they do." Conflate them and you ship a isAdmin boolean that grows into a 14-branch if tree by month six.

The 2026 pattern is RBAC with permissions attached to roles, checked at the route or component boundary:

// route handler
if (!auth.has({ permission: 'org:billing:manage' })) {
  return new Response('Forbidden', { status: 403 })
}

Clerk and Auth0 both ship this natively. For Better Auth, the Casbin plugin or a 50-line custom check works. The point is: never check user.role === 'admin' directly in business logic. That couples your code to your auth model and makes future role changes a refactor.

4. Passkey-first, password second, MFA on admin

Offer passkeys (WebAuthn) as the primary login. Fall back to email + password. Require TOTP or WebAuthn as a second factor for any user with admin privileges or sensitive data access.

The trick is not making MFA universal at signup (which kills conversion) but using step-up authentication on the routes that need it. When a user hits /admin/billing, the provider re-prompts for MFA even if they are already logged in. Clerk, Auth0, and WorkOS all expose this as a one-line API.

5. Device trust and session revocation

Every provider gives you a session list per user. Surface it in your settings UI ("Active sessions" with browser, location, last active). Let users revoke individual sessions. This is the lowest-effort security feature with the highest user trust payoff, and it costs you a single React component.

2026 anti-patterns that still ship to production

These are the patterns we still see in code reviews, in roughly the order of how badly they will hurt you.

  • Custom JWT signing with HS256 and a process.env.JWT_SECRET. The secret leaks once and every token in your system is forgeable. If you must hand-sign JWTs, use RS256 with key rotation and verify in microservices using the public key only.
  • Storing passwords without Argon2id. OWASP and NIST SP 800-63B both name Argon2id as the 2026 default. bcrypt is acceptable; MD5, SHA-256, or PBKDF2 with low iterations is malpractice. If you are using a managed provider, this is handled. If you are not, you are one breach away from a class action.
  • No rate limit on /login or /forgot-password. A single attacker with a residential proxy pool will spray credential-stuffing attacks across your user base in hours. Cloudflare Turnstile, Upstash Ratelimit, or your provider's built-in throttle. Pick one. We cover the broader Postgres query optimization angle elsewhere, but rate-limit data should sit in Redis or the edge, not in your primary DB.
  • No MFA on admin routes. Your support team's account is the highest-value target on your platform. If a support agent can refund, impersonate, or export user data without MFA, your blast radius from one phished password is the entire customer base.
  • Tokens in localStorage for non-cookie clients. Already covered, but worth repeating: localStorage is XSS-readable. Use httpOnly cookies for browser, OS keychain for native, and never the URL fragment for either.
  • Email + password as the only login option. Passkey support takes 20 lines of code in 2026 and removes 80% of your password-reset support tickets. The cost of skipping it compounds every quarter.
  • Rolling your own email verification with a 6-digit code and no expiry. Codes must expire (15 minutes max), be single-use, and be rate-limited per email. Providers do this for you.

When you can skip a managed provider entirely

Best practices have ROI curves. A few honest cases where you can skip a managed auth provider:

  • Internal tool with under 10 users behind a VPN or Tailscale. GitHub OAuth + a single allow-list check is fine.
  • Throwaway prototype. If the data is fake and the URL is unguessable, do not block on auth.
  • Single-admin side project. One basic auth header in front of an admin route is acceptable for two weeks. Not two years.

If your product has paying customers, has more than one role, or stores anything regulators care about, you are paying for managed auth. Period.

What this costs in engineer time

A working signup-login-session flow on Clerk or Auth0 takes a half-day for an engineer who has done it before. A production-ready setup with MFA, RBAC, audit logs, SSO for one enterprise customer, and password reset flows takes about a week.

Where teams burn time is the second week: the customization that providers technically support but that your engineer has to read three docs pages and a GitHub issue to figure out. SCIM provisioning. Custom OAuth scopes. Multi-tenant org switching. Session-revocation webhooks into your audit log.

This is the kind of work where every Cadence engineer is AI-native by default (vetted on Cursor, Claude Code, and Copilot fluency before they unlock bookings) and ships the integration in days instead of weeks. A senior engineer at $1,500/week is the right tier for the full production rollout. A mid engineer at $1,000/week handles the day-1 setup and the first two enterprise edge cases.

If you want a second opinion on whether your current auth stack is actually production-ready, audit your stack with Ship-or-Skip. It will tell you, in plain language, what to fix before your first SOC 2 audit asks for it.

Steps

  1. Pick your provider. Use the table above. B2C → Clerk. Enterprise → Auth0. B2B SSO → WorkOS. Own-data → Better Auth.
  2. Wire the SDK into your app. Install the package, set the publishable + secret keys in your env, wrap your app root in the provider.
  3. Add middleware. Protect your routes at the edge, not inside handlers. Use the route-matcher pattern shown above.
  4. Set up roles and permissions in the provider dashboard. Keep role for identity, permission for capability checks.
  5. Enable passkeys, then password, then TOTP MFA. Configure step-up auth for admin routes only.
  6. Ship the active-sessions UI. One component, huge trust payoff.
  7. Add rate limits to /login, /signup, /forgot-password. Cloudflare Turnstile or Upstash Ratelimit.
  8. Audit. Have a second engineer (or book a Cadence senior) read the integration with one question in mind: "what would a determined attacker try first?"

Want a sanity check before you go live? Cadence engineers ship managed-auth integrations every week. Book a senior at $1,500/week with a 48-hour free trial, and have a working production-grade auth stack inside a week. No recruiter loop, no contract, replace any week.

FAQ

Should I ever build my own authentication in 2026?

Almost never. The honest cases are an internal tool behind a VPN, a single-admin side project, or a throwaway prototype. If you have paying customers or store regulated data, pay for managed auth. The cost is a rounding error against a single breach.

Is JWT dead in 2026?

No, but raw JWT-in-localStorage is. Use signed JWTs inside httpOnly cookies, or use opaque session tokens issued by your provider. If you do sign your own JWTs, use RS256 with key rotation, never HS256 with a shared secret in .env.

How do I enforce MFA only for admin users?

Use your provider's step-up authentication API. Trigger it on route entry for admin paths, not at login. Clerk's auth.protect() with a factor requirement, Auth0's acr_values parameter, or WorkOS's MFA challenge endpoint all do this in one line.

Are passkeys ready to be the default in 2026?

Yes for B2C, mostly yes for B2B. Offer passkeys first, password second, and TOTP as MFA fallback. The browser support is universal and the user-experience win (no password reset emails) pays for itself in a single quarter.

How long does a managed-auth integration take?

A working signup-login-session flow takes a half-day. A production-ready setup with MFA, RBAC, audit logs, and SSO for one enterprise customer takes about a week. Add another week if you need SCIM provisioning or multi-tenant org switching.

All posts