Skip to main content

Introduction

WIP

Faceted, framework-agnostic, transport-pluggable authentication for modern TypeScript apps.

What is duck-auth?

duck-auth is an authentication library built around a single faceted root, AuthEngine. Every concern - sessions, identities, passwords, providers, MFA, flows, API keys, machine-to-machine, organizations, idempotency, hijack policy, anomaly detection - is a typed facet you wire once at boot and pass into the runtime.

It is framework-agnostic (Express, Hono, Next.js, Fastify, Koa, Elysia, NestJS, gRPC, vanilla Web Fetch), transport-pluggable (Cookie, Bearer, JWT, Composite, with optional DPoP binding), and batteries-included (magic-link, passkeys, six OAuth providers, SAML, password hashing, TOTP MFA, WebAuthn-MFA, channels for SMTP/Resend/SES/Twilio/WebPush, adapters for Memory/Redis/SQL).

Pairs with @gentleduck/iam for authorization. Authentication proves who the caller is; authorization decides what they may do. They are kept as two libraries on purpose - apps wire a small projectToSubject function to bridge identity and session into the iam Subject shape.

Why duck-auth?

Every TypeScript auth library forces one of three trade-offs:

  • Framework lock-in - NextAuth, Auth.js: only one runtime, one shape.
  • Hosted control plane - Clerk, WorkOS, Stytch: per-MAU pricing, vendor lock.
  • DIY on Lucia + passport + your own glue - you own every edge case.

duck-auth is the third option, unified: framework-agnostic core, batteries-included adapters, no hosted plane. You wire it into your router with one adapter import.

Key features

FeatureDescription
14-facet rootAuthEngine exposes sessions, identities, passwords, providers, mfa, flows, apiKeys, m2m, orgs, plugins, operations, idempotency, hijack, anomaly.
Framework-agnosticExpress, Hono, Next.js (app router), Fastify, Koa, Elysia, NestJS, gRPC, and a generic Web-Fetch executor.
Pluggable transportsCookieTransport, BearerTransport, JwtTransport (HS256/ES256/RS256/EdDSA), CompositeTransport, plus DPoPVerifier for RFC 9449 sender-constrained tokens.
Provider libraryPassword, magic-link, six OAuth (Google, GitHub, LinkedIn, Microsoft, Discord, Apple), WebAuthn passkeys (discoverable + username), API keys, SAML.
Storage adaptersMemory (dev/test), Redis (session/idempotency/limiter/events/DPoP nonce), SQL bridge with bundled Drizzle examples for pg / mysql / sqlite.
ChannelsConsole, SMTP, Resend, AWS SES, Twilio, WebPush, plus Test and Noop.
Strict modeAuthEngine.strict({ env: 'production' }) rejects dev-only footguns at boot: insecure cookies, AuthNoopLimiter, IamMemoryAdapter, missing lockout listeners, weak JWT keys, missing compliance presets.
Compliance presetsgdpr, hipaa, soc2, fips - strictest preset wins. Each enforces hashing, dataAtRest, channel, and anomaly minimums.
Anomaly detectionImpossible-travel and device-fingerprint detectors, plus an aggregator that emits allow / deny / step-up.
ObservabilityOpenTelemetry instrumentation, AuthWebhookDeliverer with HMAC-signed outbound delivery, OpenAPI 3.1 generator, OIDC discovery, JWKS rotation.
CLIduck-auth init, doctor, keys generate, keys rotate, migrate, emit-openapi.

Architecture

Loading diagram...

AuthEngine is the runtime entry point. You construct it once at boot, pass the transport, stores, and providers you want, and hand the resulting instance to the framework adapter that mounts the routes.

Status

Pre-1.0. v0.1 covers approximately 98% of the v1.0 MUST surface. Per-component status is tracked in STATUS.md; the architectural rationale lives in DESIGN.md.

SurfaceStatus
Core (14 facets)shipped
Transports (cookie, bearer, jwt, composite, DPoP)shipped
Adapters (memory, redis, sql bridge + Drizzle examples)shipped
Providers (password, magic-link, 6 OAuth, passkey, api-key, saml)shipped
Channels (console, smtp, resend, ses, twilio, webpush)shipped
Servers (express, hono, next, fastify, koa, elysia, nestjs, grpc, generic)shipped
Clients (vanilla, react, vue, svelte, solid)shipped
CLI (init / doctor / keys / migrate / emit-openapi)shipped
OpenAPI generator + OIDC discovery + OpenTelemetry + i18nshipped
authCreateTest() test helper + Storybook decoratorshipped
WebAuthn-MFA factorshipped
KMS-envelope DataAtRest (AuthAwsKmsProvider reference)shipped
JwtTransport (HS256 / ES256 / RS256 / EdDSA + live JWKS rotation)shipped
Native iOS / Android SDKscommunity-maintained

Next steps

  • Installation -> - install the package, scaffold via the CLI, and run the 60-second quickstart.
  • Core concepts -> - read about AuthEngine, facets, and the request lifecycle.
  • Providers -> - wire password, magic-link, OAuth, passkey, API-key, or SAML.
  • Adapters -> - Memory, Redis, SQL (Drizzle examples for pg / mysql / sqlite).
  • Security -> - production hardening, strict(), compliance presets, threat model.