Authentication Setup
Configure the Puzzle Auth client and server integrations generated by @puzzle-ui/create.
Puzzle Auth consists of two packages with separate responsibilities:
@puzzle-ui/authcontains framework-independent authentication logic.@puzzle-ui/fullstackprovides the browser client, React components, HTTP handlers, and framework adapters.
The project generator can scaffold the client integration and framework API route for Next.js and TanStack Start.
Security configuration is required
The generated authentication integration is not production-ready by itself. You must supply secure storage, password hashing, rate limiting, session, MFA, cookie, CSRF, and trusted client IP configuration before exposing authentication routes.
Generate an application
Run the Puzzle project generator:
npx @puzzle-ui/createChoose Next.js or TanStack Start and enable Puzzle Auth.
The generator installs:
npm install @puzzle-ui/auth @puzzle-ui/fullstack @puzzle-ui/sessionGenerated client integration
The generator wraps the application in AuthProvider.
import { AuthProvider } from "@puzzle-ui/fullstack/auth/client";
export const Providers = ({ children }: { children: React.ReactNode }) => (
<AuthProvider options={{ basePath: "/api/auth" }}>{children}</AuthProvider>
);The provider creates the browser authentication client and retrieves authentication state from the server.
Session credentials are managed by secure server cookies. Do not copy session tokens into local storage or session storage.
Authentication pages
The generator creates sign-in and sign-up pages using AuthExperience.
import { AuthExperience } from "@puzzle-ui/fullstack/auth/client";
export const SignInPage = () => <AuthExperience mode="sign-in" />;import { AuthExperience } from "@puzzle-ui/fullstack/auth/client";
export const SignUpPage = () => <AuthExperience mode="sign-up" />;The experience supports branding, layout, redirects, custom registration fields, and custom submission handling.
See the @puzzle-ui/fullstack package documentation for the complete AuthExperience API.
Framework API routes
Next.js
The generator creates:
src/app/api/auth/[...auth]/route.tsThe route delegates to createNextAuthHandler.
import { createNextAuthHandler } from "@puzzle-ui/fullstack/auth/next";
const handlers = createNextAuthHandler({
auth: authServer,
});
export const GET = handlers.GET;
export const POST = handlers.POST;The generated route also calls the application bootstrap and returns HTTP 503 until an AuthServer has been registered.
TanStack Start
The generator creates:
src/routes/api/auth/$.tsThe route delegates to createTanStackAuthHandler through the TanStack server route handlers.
Both adapters delegate authentication policy and security-sensitive behavior to the framework-independent authentication packages.
Basic React
A Basic React project has no server runtime.
The generator creates the AuthProvider and sign-in/sign-up components, but it does not generate a server API route.
Host the Puzzle Auth API in a separate server application. Configure the client base path to point to that API.
Configure the server
The generated Next.js and TanStack Start projects include these server-only files:
src/lib/auth/
├── server.ts
├── bootstrap.ts
└── unavailable.tsThe server.ts module exposes two functions:
configureAuthServer(server)registers the configured server.getAuthServer()returns the registered server ornull.
The bootstrap module provides one initialization point. It is intentionally left for your application to complete.
Create the AuthServer
The fullstack package expects an AuthServer assembled from the authentication managers and session configuration.
import { createAuthServer } from "@puzzle-ui/fullstack/auth/server";
import { configureAuthServer } from "./server";
import {
auth,
mfa,
stepUp,
sessions,
cookie,
csrf,
resolveClientIp,
} from "./auth-managers";
export const initializePuzzleAuth = () => {
configureAuthServer(
createAuthServer({
auth,
mfa,
stepUp,
sessions,
cookie,
csrf,
resolveClientIp,
}),
);
};This example assumes that auth-managers exports already initialized and correctly configured dependencies. It is not a complete provider implementation.
Call your application initialization from the generated bootstrap function. Ensure that initialization is safe to run once per server runtime.
Required security dependencies
Storage
The storage adapter must support the capabilities required by the authentication and session managers.
At minimum, verify:
- Unique constraints.
- Conditional writes.
- Atomic batch operations.
Do not use an in-memory adapter for production sessions, tokens, MFA factors, or other security-critical state.
Password hashing
Supply a secure password hashing implementation through the PasswordHasher interface.
Do not store plaintext passwords. Do not replace the password hasher with a fast general-purpose hash such as SHA-256.
Rate limiting
Supply a shared atomic rate limiter. A process-local counter is not sufficient for production deployments with multiple instances.
Session management
Create a StorageSessionManager using the same storage adapter and configure appropriate idle and absolute session lifetimes.
MFA
The MFA manager requires:
- A password hasher.
- A rate-limit provider.
- An authenticated session manager.
- A secret protector for TOTP secrets.
- A WebAuthn provider when passkeys are enabled.
The WebAuthn relying-party ID, name, and origin must match the actual deployment.
Cookies and CSRF
Use secure, HttpOnly cookies in production. Configure CSRF protection with the application's trusted origins.
Client IP resolution
The resolveClientIp callback must use the deployment's trusted proxy configuration.
Do not blindly trust arbitrary X-Forwarded-For values.
HTTP 503 before configuration
The generated API route deliberately returns a no-store HTTP 503 response when the application has not registered an AuthServer.
This prevents a generated but unconfigured authentication endpoint from appearing to work.
Do not remove this protection or replace it with fake managers.
Client and server boundaries
Keep these imports separate:
| Code | Allowed entry point |
|---|---|
| Browser components and hooks | @puzzle-ui/fullstack/auth/client |
| Server handlers | @puzzle-ui/fullstack/auth/server |
| Next.js adapter | @puzzle-ui/fullstack/auth/next |
| TanStack Start adapter | @puzzle-ui/fullstack/auth/tanstack |
| Shared serializable contracts | @puzzle-ui/fullstack/auth/shared |
Never import server handlers, storage adapters, password hashing implementations, or secrets into browser-facing modules.
Basic React with a separate API
For a browser-only React application, point the AuthProvider to the server API:
<AuthProvider
options={{
basePath: "https://api.example.com/api/auth",
credentials: "include",
}}
>
<App />
</AuthProvider>The API deployment must configure CORS, trusted origins, cookies, and CSRF protection for the browser application's origin.