Hono 集成
在开始之前,请确保你已配置了 Better Auth 实例。如果还没有配置,请查看安装指南。
【Before you start, make sure you have a Better Auth instance configured. If you haven't done that yet, check out the installation.】
安装处理程序
【Mount the handler】
我们需要将处理器挂载到 Hono 端点。
【We need to mount the handler to Hono endpoint.】
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);跨域资源共享 (CORS)
【Cors】
要配置 CORS,你需要使用来自 hono/cors 的 cors 插件。
【To configure cors, you need to use the cors plugin from hono/cors.】
import { Hono } from "hono";
import { auth } from "./auth";
import { serve } from "@hono/node-server";
import { cors } from "hono/cors";
const app = new Hono();
app.use(
"/api/auth/*", // or replace with "*" to enable cors for all routes
cors({
origin: "http://localhost:3001", // replace with your origin
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);重要提示: CORS 中间件必须在路由之前注册。这可以确保跨域请求在到达你的认证端点之前被正确处理。
中间件
【Middleware】
你可以添加一个中间件,将 session 和 user 保存到 context 中,并且为每个路由添加验证。
【You can add a middleware to save the session and user in a context and also add validations for every route.】
import { Hono } from "hono";
import { auth } from "./auth";
import { serve } from "@hono/node-server";
import { cors } from "hono/cors";
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({ headers: c.req.raw.headers });
if (!session) {
c.set("user", null);
c.set("session", null);
await next();
return;
}
c.set("user", session.user);
c.set("session", session.session);
await next();
});
app.on(["POST", "GET"], "/api/auth/*", (c) => {
return auth.handler(c.req.raw);
});
serve(app);这将允许你在所有路由中访问 user 和 session 对象。
【This will allow you to access the user and session object in all of your routes.】
app.get("/session", (c) => {
const session = c.get("session")
const user = c.get("user")
if(!user) return c.body(null, 401);
return c.json({
session,
user
});
});跨域 Cookie
【Cross-Domain Cookies】
默认情况下,所有 Better Auth 的 Cookie 都设置为 SameSite=Lax。如果你需要在不同域之间使用 Cookie,需要将 SameSite=None 并设置 Secure=true。然而,我们建议尽可能使用子域名,因为这样可以保持 SameSite=Lax。要启用跨子域 Cookie,只需在你的认证配置中开启 crossSubDomainCookies。
【By default, all Better Auth cookies are set with SameSite=Lax. If you need to use cookies across different domains, you’ll need to set SameSite=None and Secure=true. However, we recommend using subdomains whenever possible, as this allows you to keep SameSite=Lax. To enable cross-subdomain cookies, simply turn on crossSubDomainCookies in your auth config.】
export const auth = createAuth({
advanced: {
crossSubDomainCookies: {
enabled: true
}
}
})如果你仍然需要设置 SameSite=None 和 Secure=true,你可以通过 createAuth 配置中的 cookieOptions 全局调整这些属性。
【If you still need to set SameSite=None and Secure=true, you can adjust these attributes globally through cookieOptions in the createAuth configuration.】
export const auth = createAuth({
advanced: {
defaultCookieAttributes: {
sameSite: "none",
secure: true,
partitioned: true // New browser standards will mandate this for foreign cookies
}
}
})你还可以通过在身份验证配置中的 cookies 中设置来单独自定义 cookie 属性。
【You can also customize cookie attributes individually by setting them within cookies in your auth config.】
export const auth = createAuth({
advanced: {
cookies: {
sessionToken: {
attributes: {
sameSite: "none",
secure: true,
partitioned: true // New browser standards will mandate this for foreign cookies
}
}
}
}
})客户端配置
【Client-Side Configuration】
在使用 Hono 客户端(@hono/client)向受 Better Auth 保护的端点发起请求时,需要将其配置为在跨源请求中发送凭证(cookie)。
【When using the Hono client (@hono/client) to make requests to your Better Auth-protected endpoints, you need to configure it to send credentials (cookies) with cross-origin requests.】
import { hc } from "hono/client";
import type { AppType } from "./server"; // Your Hono app type
const client = hc<AppType>("http://localhost:8787/", {
init: {
credentials: "include", // Required for sending cookies cross-origin
},
});
// Now your client requests will include credentials
const response = await client.someProtectedEndpoint.$get();当出现以下情况时,需要进行此配置:
- 在开发过程中,客户端和服务器位于不同的域名/端口
- 在生产环境中进行跨域请求
- 需要在请求中发送身份验证 Cookie
【This configuration is necessary when:
- Your client and server are on different domains/ports during development
- You're making cross-origin requests in production
- You need to send authentication cookies with your requests】
credentials: "include" 选项告诉 fetch 客户端即使在跨域请求时也要发送 cookies。这需要配合服务器上的 CORS 配置使用,该配置设置了 credentials: true。
【The credentials: "include" option tells the fetch client to send cookies even for cross-origin requests. This works in conjunction with the CORS configuration on your server that has credentials: true.】
注意: 请确保服务器上的 CORS 配置与客户端的域名匹配,并且在服务器的 CORS 配置和客户端的 fetch 配置中都设置了
credentials: true。
Cloudflare 工作者
【Cloudflare Workers】
在将 Better Auth 与 Hono 部署到 Cloudflare Workers 时,如果你的认证配置依赖于运行时环境变量(例如 D1 数据库的 env.DB),你可能会在 CLI 中遇到问题。
【When deploying Better Auth with Hono on Cloudflare Workers, you may encounter issues with the CLI if your auth configuration depends on runtime environment variables (like env.DB for D1 databases).】
问题
【The Problem】
在 Cloudflare Workers 中,环境变量是在运行时通过请求处理程序传递的,而在构建时不能通过 process.env 获取。这使得在迁移时使用 Better Auth CLI 变得具有挑战性,因为 CLI 需要导入你的认证配置文件。
【In Cloudflare Workers, environment variables are passed at runtime through request handlers, not available via process.env at build time. This makes it challenging to use the Better Auth CLI for migrations since the CLI needs to import your auth configuration file.】
// This won't work with the CLI because env is not available
export const createAuth = (env: Env) => betterAuth({
database: env.DB, // env.DB is only available at runtime
// ... rest of config
});方案 1:程序化迁移(内置 Kysely 适配器)
【Solution 1: Programmatic Migrations (Built-in Kysely Adapter)】
如果你正在使用内置的 Kysely 适配器(SQLite/D1、PostgreSQL、MySQL),你可以通过自定义端点以编程方式运行迁移:
【If you're using the built-in Kysely adapter (SQLite/D1, PostgreSQL, MySQL), you can run migrations programmatically through a custom endpoint:】
import { Hono } from "hono";
import { getMigrations } from "better-auth/db";
import { betterAuth } from "better-auth";
type Env = {
DB: D1Database;
// ... other bindings
};
const app = new Hono<{ Bindings: Env }>();
// Migration endpoint - call this to set up your database
app.post("/migrate", async (c) => {
const authConfig = {
database: c.env.DB,
// Add all your other auth config options here
// (socialProviders, plugins, etc.)
};
try {
const { toBeCreated, toBeAdded, runMigrations } = await getMigrations(authConfig);
if (toBeCreated.length === 0 && toBeAdded.length === 0) {
return c.json({ message: "No migrations needed" });
}
await runMigrations();
return c.json({
message: "Migrations completed successfully",
tablesCreated: toBeCreated.map(t => t.table),
tablesUpdated: toBeAdded.map(t => t.table)
});
} catch (error) {
return c.json({
error: error instanceof Error ? error.message : "Migration failed"
}, 500);
}
});
// Your auth handler
app.on(["POST", "GET"], "/api/auth/*", async (c) => {
const auth = betterAuth({
database: c.env.DB,
// ... your config
});
return auth.handler(c.req.raw);
});
export default app;使用方法:
- 部署你的 worker
- 调用迁移端点一次:
curl -X POST https://your-worker.workers.dev/migrate - 运行后删除或保护迁移端点
安全提示:在生产环境中保护你的迁移端点!请考虑:
- 添加身份验证/授权
- 使用基于环境的检查,仅允许在开发环境中进行迁移
- 在初始设置完成后完全移除该端点
方案 2:使用 cloudflare:workers 导入(Prisma/Drizzle)
【Solution 2: Use cloudflare:workers Import (Prisma/Drizzle)】
对于 Prisma 或 Drizzle 用户,Cloudflare 现在支持从 cloudflare:workers 导入环境变量:
【For Prisma or Drizzle users, Cloudflare now supports importing environment variables from cloudflare:workers:】
import { env } from "cloudflare:workers";
import { drizzle } from "drizzle-orm/d1";
import { betterAuth } from "better-auth";
export const auth = betterAuth({
database: drizzle(env.DB),
// ... rest of your config
});这允许你使用标准的命令行接口命令:
【This allows you to use the standard CLI commands:】
npx @better-auth/cli generate有关此功能的更多详情,请查看Cloudflare 更新日志。
【See the Cloudflare changelog for more details on this feature.】
解决方案 3:使用带兼容性标志的 process.env
【Solution 3: Use process.env with Compatibility Flag】
将 nodejs_compat_populate_process_env 标志添加到你的 wrangler.toml 中:
【Add the nodejs_compat_populate_process_env flag to your wrangler.toml:】
compatibility_flags = ["nodejs_compat_populate_process_env"]然后在你的认证配置中使用 process.env:
【Then use process.env in your auth config:】
import { drizzle } from "drizzle-orm/d1";
import { betterAuth } from "better-auth";
export const auth = betterAuth({
database: drizzle(process.env.DB as any),
// ... rest of config
});对于 2025-04-01 或之后的兼容日期,当启用 nodejs_compat 时,这是默认行为。更多详情请参阅 Cloudflare 文档。
【For compatibility dates on or after 2025-04-01, this is the default behavior when nodejs_compat is enabled. See the Cloudflare documentation for more details.】
有关编程迁移的更多信息,请参阅 数据库文档。