Use Better Auth with DaloyJS
Better Auth is a TypeScript authentication framework you host in your own application. Unlike Auth0, Okta, Clerk, or LoginRadius, it is not only a hosted identity provider integration. Your app owns the auth tables, the session cookies, and the auth endpoints.
Better Auth already documents Hono, Elysia, and Fastify adapters. DaloyJS does not need a special adapter because both libraries meet at the Web-standard boundary: Better Auth exposes auth.handler(request)and DaloyJS gives every route and hook the original Request.
- 01requestBrowserDaloyJSPOST /api/auth/sign-in/emailcredentials, OAuth callbacks, session actions
- 02asyncDaloyJSBetter Authauth.handler(request)mounted under /api/auth/*
- 03asyncBetter AuthDatabaseusers, accounts, sessions
- 04responseBetter AuthBrowserResponse with Set-Cookie
- 05requestBrowserDaloyJSGET /me with session cookie
- 06asyncDaloyJSBetter Authauth.api.getSession({ headers })
1. Install
2. Create the auth instance
Configure Better Auth once and export the instance. Use the database adapter that matches your app. The example below keeps the database placeholder explicit because production apps should not copy a toy in-memory store into auth.
3. Environment variables
4. Mount Better Auth routes
Better Auth owns all routes below /api/auth/*. Return the raw Response from a preBody hook so cookies, redirects, status codes, and multiple Set-Cookie headers are preserved exactly. preBody runs after routing but before any body I/O, which is the right place to delegate to another web-standard Request → Response handler. Because Better Auth owns the successful response body, cookies, and redirects, both routes explicitly set acknowledgeNoResponseBodySchema: true.
5. Protect DaloyJS routes
Use auth.api.getSession({ headers }) inside apreBody guard. Because it only reads headers (no body parsing needed), it runs in the cheapest-rejection phase before validated context is built. This keeps normal DaloyJS routes contract-first while Better Auth owns the session lookup.
Client usage
Browser apps use Better Auth's client. Point baseURL at the same origin or public API origin that serves your DaloyJS app.
Runtime fit
| Runtime | Fit | Notes |
|---|---|---|
| Node.js | Recommended | Best default for database-backed sessions and OAuth callbacks. |
| Bun / Deno | Depends on adapter | Use only with database drivers tested on that runtime. |
| Cloudflare Workers | Depends on adapter | The auth handler is Web-standard, but your database adapter must also work on Workers. |
| Vercel | Yes | Use Node functions unless every selected adapter is edge-safe. |
| AWS Lambda | Yes | Use pooled or serverless database access. |
Security notes
- 01configSecretBETTER_AUTH_SECRET from a real secret manager
- 02OrigintrustedOrigins pins browser origins
- 03Cookiespreserve raw Response from auth.handler
- 04Proxydeclare TRUST_PROXY_HOPS behind a platform edge
- 05Databasemigrate auth tables before traffic
- Generate a strong
BETTER_AUTH_SECRETand rotate it with the same care as a JWT signing key. - Keep
trustedOriginsnarrow. Do not allow arbitrary origins in production. - Preserve Better Auth's raw
Responsefor auth endpoints. Rebuilding headers into a plain object can collapse multipleSet-Cookieheaders. - When deployed behind Railway, Render, Fly.io, Vercel, Cloudflare, or another edge proxy, configure DaloyJS's proxy posture so generated URLs, cookies, rate limiting, and audit logs use the expected origin and client IP.
- Put
rateLimit()in front of sign-in, sign-up, password reset, and callback routes. Better Auth handles auth logic, but the API still needs abuse controls.
See also the auth integrations overview, Better Auth installation, Better Auth basic usage, and the framework integration docs for Hono, Elysia, and Fastify.