mcpField
A
api-auth-better-auth-drizzle-hono

api-auth-better-auth-drizzle-hono

github.com/agents-inc安全2678 次安装2 天前更新
代码仓库

关于 api-auth-better-auth-drizzle-hono

面向使用 Better Auth 的 TypeScript 开发者,提供认证配置、会话、插件和数据库迁移指南,涵盖邮箱密码、OAuth、双重验证及组织多租户。

主要功能

  1. 01服务端配置与数据库适配器
  2. 02类型安全的会话中间件
  3. 03邮箱与密码认证流程
  4. 04OAuth 与双重验证
  5. 05组织多租户
  6. 06数据库、Cookie 缓存与无状态会话

适用场景

  1. 01为 TypeScript 应用添加自托管认证
  2. 02使用类型安全会话保护路由
  3. 03配置 OAuth 和双重验证登录
  4. 04选择会话策略

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agents-inc/skills --skill api-auth-better-auth-drizzle-hono

安装后在 Claude Code 中输入/api-auth-better-auth-drizzle-hono确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

metadata.yaml
reference.md
examples/
core.md
oauth.md
organizations.md
sessions.md
two-factor.md

详细介绍

使用 Better Auth 进行身份验证

快速指南: 在 TypeScript 应用中使用 Better Auth(v1.5+)实现类型安全、可自托管的身份验证。它提供电子邮件/密码、OAuth、2FA、会话、无状态身份验证和组织多租户功能。插件架构支持渐进式扩展。请在依赖会话的中间件之前挂载身份验证处理程序;跨源部署时,请先配置 CORS;添加插件后,务必运行架构生成命令。


<critical_requirements>

关键:使用此技能前

(必须在任何依赖会话的其他中间件之前,将 Better Auth 处理程序挂载到身份验证路由上)

(客户端与服务端位于不同源时,必须在身份验证路由之前配置 CORS 中间件)

(所有密钥(clientId、clientSecret、BETTER_AUTH_SECRET)必须使用环境变量,绝不硬编码)

(添加插件后,必须先运行 npx auth@latest generate,再运行 ORM 迁移工具)

(必须使用 auth.$Infer.Session 类型,在中间件中以类型安全的方式访问会话)

</critical_requirements>


自动检测: Better Auth、betterAuth、createAuthClient、auth.handler、auth.api.getSession、socialProviders、twoFactor 插件、organization 插件、drizzleAdapter、会话管理、OAuth 提供方、无状态会话、cookieCache、genericOAuth、oAuthProvider、passkey、SCIM

适用场景:

  • 构建可自托管的身份验证(避免被供应商锁定)
  • 需要在一个解决方案中实现电子邮件/密码 + OAuth + 2FA
  • 具有组织/团队管理功能的多租户 SaaS
  • 类型安全的会话管理
  • 需要将会话存储在数据库中或使用无状态会话的项目

不适用场景:

  • 需要免维护的托管身份验证(可考虑托管身份验证解决方案)
  • 没有用户账户的简单静态网站
  • 无服务器冷启动至关重要的项目(不过无状态模式有所帮助)

涵盖的关键模式:

  • 带插件的服务端配置(auth.ts)
  • 会话中间件与类型安全的路由保护
  • 电子邮件/密码身份验证流程
  • OAuth 提供方(GitHub、Google、Generic OAuth)
  • 双重身份验证(TOTP)
  • 组织与多租户
  • 会话策略:数据库、Cookie 缓存、无状态
  • 数据库适配器集成
  • 客户端 useSession 钩子
  • 性能:实验性联接、Cookie 缓存、无状态会话

详细资源:


设计理念

Better Auth 采用以 TypeScript 为先、可自托管的身份验证方式。用户数据保留在你的数据库中,不会被供应商锁定。插件架构支持渐进式扩展——从简单配置开始,并根据需要添加功能。

核心原则:

  1. 全面保障类型安全 - 会话类型通过 auth.$Infer.Session 从服务端传递到客户端
  2. 以数据库为事实来源 - 会话存储在你的数据库中(可选无状态模式)
  3. 基于插件的可扩展性 - 按需添加 2FA、组织、通行密钥、SCIM、OAuth 提供方
  4. 与框架无关 - 适用于任何 TypeScript Web 框架
  5. 注重性能 - 实验性联接(快 2-3 倍)、Cookie 缓存、无状态会话

核心模式

模式 1:服务配置(auth.ts)

创建带数据库适配器的 auth 实例。这是所有身份验证配置的唯一事实来源。

// lib/auth.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { db } from "@/lib/db";

const SESSION_EXPIRES_IN_SECONDS = 60 * 60 * 24 * 7; // 7 days
const SESSION_UPDATE_AGE_SECONDS = 60 * 60 * 24; // Refresh daily

export const auth = betterAuth({
  database: drizzleAdapter(db, { provider: "pg" }),
  emailAndPassword: {
    enabled: true,
    minPasswordLength: 8,
    maxPasswordLength: 128,
  },
  session: {
    expiresIn: SESSION_EXPIRES_IN_SECONDS,
    updateAge: SESSION_UPDATE_AGE_SECONDS,
  },
  trustedOrigins: [process.env.APP_URL || "http://localhost:3000"],
});

优点: 命名常量让会话策略易于审计,URL 使用环境变量,并且只导出一个实例

// BAD: Magic numbers, hardcoded secrets, default export
const auth = betterAuth({
  database: { url: "postgres://user:pass@localhost/db" },
  session: { expiresIn: 604800 },
});
export default auth;

缺点: 硬编码凭据会泄露到源代码管理中,魔法数字让策略难以理解,使用默认导出

完整设置(含电子邮件验证和 Drizzle 适配器配置)请参见 examples/core.md。


模式 2:具备类型安全的会话中间件

挂载 auth 处理程序,并创建用于在路由中访问会话的类型化中间件。

// CRITICAL: CORS must be configured BEFORE auth routes
app.use("/auth/*", cors({ origin: APP_URL, credentials: true }));
app.on(["POST", "GET"], "/auth/*", (c) => auth.handler(c.req.raw));
// middleware/auth-middleware.ts - Type-safe session access
type AuthVariables = {
  user: typeof auth.$Infer.Session.user | null;
  session: typeof auth.$Infer.Session.session | null;
};

export const authMiddleware = createMiddleware<{ Variables: AuthVariables }>(
  async (c, next) => {
    const session = await auth.api.getSession({ headers: c.req.raw.headers });
    c.set("user", session?.user ?? null);
    c.set("session", session?.session ?? null);
    await next();
  },
);

优点: auth.$Infer.Session 可确保 c.get("user") 的类型正确,先配置 CORS 再配置 auth 可避免预检请求失败,c.req.raw 提供 Better Auth 所需的 Web 标准 Request

// BAD: No type annotation - c.user is any, bypasses type system
app.use("*", async (c, next) => {
  const session = await auth.api.getSession({ headers: c.req.raw.headers });
  c.user = session?.user; // any - no autocomplete
  await next();
});

缺点: 没有 AuthVariables 类型意味着任何访问都将失去类型检查,直接赋值属性会绕过类型化 Variables

受保护路由模式请参见 examples/core.md。


模式 3:插件添加后生成架构

每个插件都会添加数据库表。添加或修改插件后,请运行 CLI:

# Step 1: Generate Better Auth schema (outputs ORM-specific files)
npx auth@latest generate

# Step 2: Generate migration with your ORM tool
npx drizzle-kit generate

# Step 3: Apply migration
npx drizzle-kit migrate

务必运行全部 3 个步骤。Better Auth 的 migrate 命令仅适用于 Kysely 适配器;对于 Drizzle,请使用 generate + Drizzle Kit。


模式 4:电子邮件/密码与验证

配置带验证和密码重置回调的电子邮件/密码身份验证。

export const auth = betterAuth({
  database: drizzleAdapter(db, { provider: "pg" }),
  emailAndPassword: {
    enabled: true,
    minPasswordLength: 8,
    maxPasswordLength: 128,
    requireEmailVerification: true,
    sendResetPassword: async ({ user, url }) => {
      await sendEmail({
        to: user.email,
        subject: "Reset password",
        html: `<a href="${url}">Reset</a>`,
      });
    },
  },
  emailVerification: {
    sendVerificationEmail: async ({ user, url }) => {
      await sendEmail({
        to: user.email,
        subject: "Verify email",
        html: `<a href="${url}">Verify</a>`,
      });
    },
  },
});

优点: 电子邮件验证可防止虚假注册,密码要求在服务器端强制执行

包含错误处理的客户端注册/登录钩子请参见 examples/core.md。


模式 5:会话策略

三种会话方案,各有不同的权衡:

策略需要数据库可撤销适用场景
数据库(默认)是是大多数应用
Cookie 缓存 + 数据库是是(延迟)减轻数据库负载
无状态否否(仅限版本)边缘/无服务器
// Cookie cache: reduces DB hits by caching session in signed cookie
session: {
  cookieCache: { enabled: true, maxAge: CACHE_SECONDS, strategy: "compact" },
}

// Stateless: omit database option entirely
const auth = betterAuth({
  // No database = fully stateless
  session: { cookieCache: { enabled: true, strategy: "jwe" } },
});

Cookie 缓存策略:compact(最小,内部使用)、jwt(标准格式,可由第三方验证)、jwe(加密,隐藏数据)。

完整配置和撤销模式请参见 examples/sessions.md。


<red_flags>

高风险事项

  • 硬编码密钥(源代码中的 clientId/clientSecret)——必须使用环境变量
  • 在 auth 路由之后配置 CORS——预检请求会失败
  • 缺少 BETTER_AUTH_SECRET 环境变量——会话将无法工作
  • 添加插件后未生成架构——运行时会出现数据库错误
  • 会话中间件未指定类型——失去 TypeScript 类型安全,c.user 会变成 any
  • 对 Drizzle 适配器使用 auth.migrate()——仅适用于 Kysely,请使用 generate + Drizzle Kit
  • 调用 auth.handler() 时缺少 c.req.raw——必须传入原始 Web 标准 Request

注意事项与边缘情况:

  • Google 仅在首次授权时签发刷新令牌——请使用 accessType: "offline" 和 prompt: "consent"
  • GitHub OAuth 应用不会签发刷新令牌(访问令牌的有效期很长)
  • 无状态会话无法单独撤销——递增 version 可使所有会话失效
  • 在其他设备上,Cookie 缓存撤销要等到 maxAge 到期后才生效
  • 跨域部署时,会话 Cookie 需要设置 SameSite=None + Secure
  • authClient.forgotPassword 在 v1.4 中更名为 authClient.requestPasswordReset
  • InferUser/InferSession 在 v1.5 中移除——请使用 better-auth 中的泛型 User 和 Session 类型

反模式的代码示例、决策框架和版本说明请参见 reference.md。

</red_flags>


<critical_reminders>

重要提醒

(必须在任何依赖会话的其他中间件之前,将 Better Auth 处理程序挂载到身份验证路由上)

(当客户端和服务器位于不同源时,必须在身份验证路由之前配置 CORS 中间件)

(必须使用环境变量存储所有密钥(clientId、clientSecret、BETTER_AUTH_SECRET)——绝不硬编码)

(添加插件后,必须先运行 npx auth@latest generate,然后再运行 ORM 迁移工具)

(必须在中间件中使用 auth.$Infer.Session 类型,以类型安全的方式访问会话)

不遵守这些规则将导致身份验证失败、安全漏洞或运行时错误。

</critical_reminders>

评论

支持 Markdown