Hono Integration
Faire Auth is built on Hono. The auth.app returned by faireAuth() is a standard Hono app, and auth.handler is a Hono fetch handler. This means Faire Auth integrates with Hono natively — no adapters, no wrappers.
Basic Setup
Mount as a route
The simplest approach — mount the auth handler on a wildcard route:
import { Hono } from "hono";
import { auth } from "./auth";
import { serve } from "@hono/node-server";
const app = new Hono();
app.on(["POST", "GET"], "/api/auth/*", (c) => {
return auth.handler(c.req.raw);
});
serve(app);Mount the app directly
Since auth.app is a Hono app, you can mount it directly using .route(). This preserves full type inference:
import { Hono } from "hono";
import { auth } from "./auth";
import { serve } from "@hono/node-server";
const app = new Hono();
// Mount the auth Hono app directly
app.route("/", auth.app);
serve(app);Edge runtimes
The handler natively supports Cloudflare Workers, Deno, and Bun — no adapter needed:
import { auth } from "./auth";
export default {
fetch(request: Request, env: Env, ctx: ExecutionContext) {
return auth.handler(request, env, ctx);
},
};Session Middleware
Add a middleware that resolves the session for all your routes. Since Faire Auth uses the two-arg API calling convention, pass the input as the first arg and headers as the second:
import { Hono } from "hono";
import { auth } from "./auth";
import { serve } from "@hono/node-server";
const app = new Hono<{
Variables: {
user: typeof auth.$Infer.Session.user | null;
session: typeof auth.$Infer.Session.session | null;
};
}>();
app.use("*", async (c, next) => {
const session = await auth.api.getSession(
{ query: {} },
{ headers: c.req.raw.headers },
);
if (!session || session.success === false) {
c.set("user", null);
c.set("session", null);
return next();
}
c.set("user", session.data.user);
c.set("session", session.data.session);
return next();
});
app.on(["POST", "GET"], "/api/auth/*", (c) => {
return auth.handler(c.req.raw);
});
serve(app);Now you can access the session in any route:
app.get("/me", (c) => {
const user = c.get("user");
if (!user) return c.json({ error: "Not authenticated" }, 401);
return c.json({ user });
});Accessing auth.api from Hono Routes
You can call any Faire Auth API endpoint directly from your Hono routes. This is useful for server-side operations that need auth context:
app.post("/admin/create-user", async (c) => {
const { email, password, name } = await c.req.json();
const result = await auth.api.signUpEmail({
json: { email, password, name },
});
if (result.success === false) {
return c.json({ error: result.message }, 400);
}
return c.json({ user: result.data.user });
});CORS
Configure CORS using Hono's built-in middleware. CORS must be registered before your routes:
import { Hono } from "hono";
import { cors } from "hono/cors";
import { auth } from "./auth";
import { serve } from "@hono/node-server";
const app = new Hono();
app.use(
"/api/auth/*",
cors({
origin: "http://localhost:3001",
allowHeaders: ["Content-Type", "Authorization"],
allowMethods: ["POST", "GET", "OPTIONS"],
exposeHeaders: ["Content-Length"],
maxAge: 600,
credentials: true,
}),
);
app.on(["POST", "GET"], "/api/auth/*", (c) => {
return auth.handler(c.req.raw);
});
serve(app);Cross-Domain Cookies
By default, all Faire Auth cookies are set with SameSite=Lax. If you need cookies across different domains, you have two options:
Cross-subdomain cookies (recommended)
If your client and server share a parent domain (e.g. app.example.com and api.example.com), enable cross-subdomain cookies:
import { faireAuth, defineOptions } from "faire-auth";
const cfg = defineOptions({
baseURL: "http://localhost:3000",
advanced: {
crossSubDomainCookies: {
enabled: true,
},
},
});
export const auth = faireAuth(cfg);Full cross-origin cookies
For completely different domains, set SameSite=None:
const cfg = defineOptions({
baseURL: "http://localhost:3000",
advanced: {
defaultCookieAttributes: {
sameSite: "none",
secure: true,
partitioned: true,
},
},
});You can also customize individual cookie attributes:
const cfg = defineOptions({
baseURL: "http://localhost:3000",
advanced: {
cookies: {
sessionToken: {
attributes: {
sameSite: "none",
secure: true,
partitioned: true,
},
},
},
},
});Using Hono's RPC Client
When using Hono's typed RPC client (hono/client) to call your own routes (not auth routes), configure it to send credentials:
import { hc } from "hono/client";
import type { AppType } from "./server";
const client = hc<AppType>("http://localhost:8787/", {
init: {
credentials: "include",
},
});
const response = await client.me.$get();For auth routes, use createAuthClient from faire-auth/client — it handles session management, reactive hooks, and the full typed proxy. Hono's hc client is for your own app routes, not for calling Faire Auth endpoints.