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:

server.ts
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:

server.ts
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:

worker.ts
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:

server.ts
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:

server.ts
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:

If your client and server share a parent domain (e.g. app.example.com and api.example.com), enable cross-subdomain cookies:

auth.ts
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:

auth.ts
const cfg = defineOptions({
    baseURL: "http://localhost:3000",
    advanced: {
        defaultCookieAttributes: {
            sameSite: "none",
            secure: true,
            partitioned: true,
        },
    },
});

You can also customize individual cookie attributes:

auth.ts
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:

api.ts
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.

On this page