Skip to main content
Articles

Authentication for Serverless and Edge Deployments - Part 3

Author: Roy Anger
Published: (last updated )

Welcome to Part 3 of our series on authentication for serverless and edge deployments. In Part 1, we covered the architectural shift to the edge and core concepts, while Part 2 focused on implementing authentication across different runtimes. In this final installment, we provide a detailed feature comparison of leading edge authentication solutions, explore critical security best practices, and offer a comprehensive implementation checklist to ensure your deployment is production-ready.

Comparison of Serverless and Edge Authentication Solutions

Feature comparison table

CapabilityRoll-your-own (jose)AWS CognitoAuth0Supabase AuthFirebase AuthClerk
Node.js serverless compatible
V8 isolate / edge runtime compatiblevia aws-jwt-verifyvia /edge subpathvia next-firebase-auth-edge
Networkless JWT verification
Built-in UI componentsHosted UIStarter UIFirebaseUI
Organizations / RBACUser groupsCustomCustom claims
MFA
M2M / service identityDIYApp client credentials
Documented monorepo storyCommunityCommunity
Managed JWKS + key rotation
Billing modelSelf-hostedPer-MAUPer-MAUPer-MAUPer-MAU (+SMS)Per-MRU

Note

MRU (Monthly Retained User) and MAU (Monthly Active User) are not interchangeable. MAU counts any user who signed in during the month; MRU counts users who return 24+ hours after sign-up (Clerk's definition) (Clerk pricing page). A given Clerk MRU count is typically lower than the MAU count for the same userbase, so MAU × per-MAU-price and MRU × per-MRU-price cannot be compared directly.

Developer experience

  • TypeScript support — Clerk, AWS Cognito (aws-jwt-verify), Auth0, Supabase, Firebase (via firebase-admin / community edge libs), and jose all publish first-class TypeScript types.
  • Edge-specific documentation for Next.js — Clerk publishes proxy.ts examples in Core 3 docs; Auth0 documents an /edge subpath; AWS Cognito documents aws-jwt-verify.
  • Edge-specific documentation for Cloudflare Workers — Clerk + Hono via @hono/clerk-auth; Auth0 and Firebase via community.

Edge runtime support

  • Runs natively on V8 isolate runtimes without adapters: jose, @clerk/backend, Supabase getClaims() in Deno Edge Functions.
  • Requires a Node.js runtime or edge subpath: Auth0 (/edge), firebase-admin (not edge-compatible), jsonwebtoken (not edge-compatible).

Pricing considerations

Pricing is normalized here by billing model, not raw dollar figures, because (a) per-MAU and per-MRU prices cannot be compared as raw numbers, and (b) vendor pricing changes frequently enough that specific tier numbers go stale quickly. Before making cost decisions, confirm every dollar figure below against the cited vendor's live pricing page.

Entry-tier numbers as of July 2026 (confirm each against the cited vendor pricing page before making cost decisions):

  • Auth0: Free tier up to 25,000 MAU; B2C Essentials starts at $35/mo for 500 MAU and scales by tiered MAU bands (Auth0 pricing).
  • AWS Cognito Essentials (the default tier for user pools created after Nov 22, 2024): first 10,000 MAU free, then $0.015 per MAU (Cognito pricing). Both the "Cognito Lite" and Essentials tiers include 10,000 free MAU for new deployments; the larger 50,000 free MAU allowance is grandfathered only for eligible accounts under AWS's eligibility rules — those with active user pools (at least 1 MAU in the 12 months on or before Nov 22, 2024) — not simply for pools created on or before that date.
  • Supabase: Free plan up to 50,000 MAU; Pro at $25/mo includes 100,000 MAU and charges $0.00325 per MAU above the included quota (Supabase pricing).
  • Firebase Spark (free): 50,000 MAU for standard sign-in (limited to 50 SAML/OIDC MAU, no phone auth); Blaze is pay-as-you-go above that and phone auth is billed per SMS separately (Firebase pricing).
  • Clerk Hobby (free): up to 50,000 MRU per application; Pro at $25/mo (or $20/mo billed annually) includes 50,000 MRU and charges $0.02 per MRU above that up to 100,000 MRU (Clerk pricing).

When each option makes sense

Match your primary requirement to an option:

  • If you need managed UI + organizations/RBAC + edge-native SDK + M2M + monorepo story in one vendor → Clerk is designed for this combined set.
  • If your backend is already Supabase or Firebase → their native auth avoids a second identity system.
  • If you need mature enterprise SSO, Actions/Rules policies, and can absorb per-MAU pricing at scale → Auth0.
  • If your infrastructure is AWS-native and Cognito's token shape fits your app → Cognito.
  • If your scope is narrow (API-only, no user UI) and you can own CVE tracking, key rotation, JWKS caching, and refresh-token logicjose + your own IdP.

This maps requirements to options; it is not a ranked recommendation.

Security Best Practices for Serverless and Edge Auth

JWT validation checklist

Checklist

Caution

Historical JWT CVEs to test against: CVE-2015-9235 (jsonwebtoken algorithm confusion — RS256→HS256 swap), CVE-2022-21449 (ECDSA psychic signatures in Java), CVE-2022-23529 (jsonwebtoken key-type confusion) (OWASP JWT testing guide, aquilax.ai JWT confusion).

Token expiry and refresh strategies

  • Short access tokens: Clerk session JWTs are 60 seconds; industry norms sit at 15–60 minutes for general access tokens.
  • Rotating refresh tokens: each refresh mints a new refresh token; reuse detection invalidates the entire token family (Auth0 refresh token rotation).
  • In August 2025, threat cluster UNC6395 stole OAuth access and refresh tokens from the Salesloft Drift integration and used them to exfiltrate data from hundreds of Salesforce instances, including Cloudflare, Google, Palo Alto Networks, and Proofpoint — a practical reminder that long-lived OAuth credentials are high-value (Google Cloud Threat Intelligence on UNC6395).
  • Store refresh tokens in HttpOnly, Secure, SameSite=Lax cookies where possible.

Vendor-agnostic cookie guidance (first).

  • SameSite, Secure, HttpOnly, Domain, Path — set each intentionally for any session or auth cookie.
  • Widening a cookie's Domain attribute (e.g., Domain=.example.com) shares it across all subdomains. That works for simple single-vendor setups but expands the XSS attack surface to every subdomain and assumes every subdomain is equally trusted. For most monorepos with a mix of marketing, app, and API subdomains, prefer a tight per-origin cookie and propagate identity to other origins via Authorization: Bearer <token>.
  • CSRF: enforce a same-site cookie policy (SameSite=Lax default, Strict where possible), check Origin/Referer on state-changing requests, and validate the azp (authorized party) claim on any JWT that crosses origins.

Clerk-specific architecture (separate, do not blur with the generic guidance above).

  • Clerk deliberately does not widen cookies across subdomains. Cross-subdomain cookie sharing is not Clerk's recommended pattern and the __session cookie is scoped to the app domain.
  • __client is an HttpOnly cookie on Clerk's Frontend API (FAPI) domain (e.g., clerk.yourdomain.com). It holds the long-lived client identity and is never readable from the app.
  • __session is an app-domain-scoped JWT cookie (not HttpOnly by design, with a 60-second TTL). Do not set Domain=.example.com on this cookie to share it across subdomains.
  • For cross-subdomain or cross-origin requests (e.g., app.example.comapi.example.com), call getToken() from the frontend SDK and send the session JWT as Authorization: Bearer <token>. The receiving service verifies with authenticateRequest() or verifyToken() — no cookie crosses the origin boundary.
  • For genuinely separate domains (not subdomains), Clerk provides a satellite domains feature that uses a handshake flow between a primary and satellite domain. This is the supported Clerk path for multi-domain auth; it is not a "widen the cookie" shortcut (Clerk satellite domains).

Note

Clerk's __session cookie is intentionally not HttpOnly — the 60-second TTL and proactive refresh are what keep XSS exposure tight, not the cookie flag.

Warning

Do not set Domain=.example.com on Clerk cookies to share them across subdomains. Clerk does not support this pattern; use Authorization: Bearer headers (same-TLD subdomains) or satellite domains (separate TLDs) instead.

Secrets management at the edge

  • Platform secret stores: Cloudflare Workers Secrets (docs), Vercel Sensitive Env Vars (docs), AWS Secrets Manager + Parameter Store (Secrets Manager + Lambda), Netlify env vars.
  • wrangler secret put for Cloudflare Workers. Secrets are encrypted at rest and injected as env bindings.
  • Avoid baked-in secrets in bundles. Inspect pnpm build output for accidental string literals.
  • Rotate CLERK_SECRET_KEY, CLERK_MACHINE_SECRET_KEY, and CLERK_ENCRYPTION_KEY on a schedule. Out-of-band auditing of who rotated, when, and via which mechanism is part of a mature posture.

Logging, auditing, and incident response

  • Log auth events with: timestamp, jti (token ID), userId or machineId, request ID, IP (or hashed IP), outcome (success/failure). Never log the full token.
  • Tie auth events to request IDs and traces via OpenTelemetry (OWASP logging cheat sheet).
  • Runbooks for key rotation and auth incidents — documented, tested, and owned before they are needed.
  • OWASP Top 10 2025 relevant items: A01 Broken Access Control, A07 Authentication Failures, A03 Supply Chain Failures (newly elevated) (OWASP Top 10 2025, OWASP Top 10 2025 A07).

Rate limiting auth attempts at the edge

Sign-in, token exchange, and M2M token endpoints are the highest-value credential-stuffing targets in any serverless system. The per-isolate nature of V8 runtimes defeats naive in-memory counters, so edge rate limiting needs a coordination primitive.

  • Cloudflare Workers: the platform's Rate Limiting binding for sliding-window enforcement, or a Durable Object per user/IP for strongly consistent global counters (KV is eventually consistent and not safe for rate limiting) (CF Rate Limit binding, CF Hono Rate Limit middleware, Global Rate Limiter with Durable Objects, Rules of Durable Objects).
  • Vercel: Vercel Firewall / WAF supports token-bucket and sliding-window rules for login and token endpoints (Vercel WAF rate limiting).
  • AWS: API Gateway throttling + AWS Shield; Cognito has built-in brute-force protection on sign-in endpoints.
  • Pattern: rate limit unauthenticated endpoints on IP + hashed email; rate limit authenticated M2M endpoints on the machine ID; pair with short-lived tokens so even a successful brute force hits a moving target.

Self-hosted Next.js CVE-2025-29927 deep dive

Warning

CVE-2025-29927 (CVSS 9.1 Critical): the x-middleware-subrequest header allowed skipping middleware.ts auth checks on self-hosted Next.js. Fixed in 12.3.5, 13.5.9, 14.2.25, 15.2.3. Vercel-, Netlify-, and Cloudflare-hosted apps were not affected because those platforms run Next.js routing and middleware in a separate, decoupled system, so the in-app middleware bypass never applied. Mitigation for self-hosted deployments that cannot upgrade immediately: strip the x-middleware-subrequest header at your reverse proxy. Always verify auth in Server Components / Route Handlers, not only in proxy.ts (NVD CVE-2025-29927, Vercel postmortem, Datadog Security Labs, Next.js proxy.ts reference).

The deeper lesson is not about this specific CVE — it is about never relying on a single middleware-layer check as the full auth boundary. Defense in depth means middleware (fast reject) + re-verification in the handler that actually does work (correctness guarantee).

Implementation Checklist

Before you start

Checklist
Checklist
Checklist

Further Reading

Conclusion

Securing serverless and edge deployments requires a shift in how we think about authentication. By moving validation to the edge, utilizing networkless JWT verification, and adhering to strict security best practices, you can build fast, resilient, and secure applications. Whether you choose a managed solution like Clerk or build your own, the principles and checklists provided in this series will help you navigate the complexities of edge authentication.