Docs/Start here

Configure the server

Build a complete Auth Dance server with components, channels, storage, a secret, and an optional route prefix.

The server needs five things: a choreography, named components, delivery channels, storage, and a base64url secret. Construct them once and hand the options to createAuthDance.

A complete memory setup

The memory providers make a compact local example. Their data lives only for the lifetime of the process.

import { AuthDanceStorage, createAuthDance, sequence } from "auth-dance";
import { EmailAuthDanceComponent } from "auth-dance/components/email";
import { PasswordAuthDanceComponent } from "auth-dance/components/password";
import {
  MemoryAuthDanceChannel,
  MemoryIdentityProvider,
  MemoryKvProvider,
  MemoryRateLimiterProvider,
} from "auth-dance/providers/memory";

const auth = createAuthDance({
  api: {
    choreography: sequence("email", "password"),
    components: {
      email: new EmailAuthDanceComponent({ channel: "email", challenge: "otp" }),
      password: new PasswordAuthDanceComponent(passwordPepper),
    },
    channels: { email: new MemoryAuthDanceChannel("email") },
    secret,
    storage: new AuthDanceStorage({
      identity: new MemoryIdentityProvider(),
      kv: new MemoryKvProvider(),
      rate_limiter: new MemoryRateLimiterProvider(),
    }),
  },
  app: { basePath: "/api/auth" },
  info: { title: "Auth API", version: "1.0.0" },
});

Generate secret as base64url data and keep it outside source control. The password component takes a separate pepper.

Pick the server surface

Surface Use it when
auth.fetch Your runtime accepts a standard Request handler.
auth.app You want to mount the Hono app in a larger application.
auth.api The caller runs in-process and does not need HTTP.
auth.generateOpenAPISchema() You need an OpenAPI description of the mounted routes.

When app.basePath is set, every Auth Dance route receives that prefix. Give the same URL to AuthDanceClient.

Keep names aligned

The choreography contains component names, and each name must exist in api.components. A component can refer to a channel by name; that channel must exist in api.channels.

sequence("email", "password")
//         │          └── api.components.password
//         └───────────── api.components.email