add-auth 是做什么的?
将本插件中经过测试的认证模板复制到用户项目中并完成接入。不要从头编写认证代码,也不要修改模板中的安全逻辑;仅调整边缘部分(数据库访问、导入、UI)。
模板位于 <skill-dir>/../../templates/,其中 <skill-dir> 是本技能的基础目录:
templates/fastapi/auth/– FastAPI 包:config.py、security.py、models.py、db.py、deps.py、routes.py、email.py;测试位于templates/fastapi/tests/test_auth.py。templates/node/lib/auth/core.ts– 无框架核心(哈希、访问令牌和重置令牌、Cookie 选项),附带core.test.ts。templates/nextjs/– 基于核心的 Next.js App Router 层:lib/auth/{schema,users,session,email}.ts、app/(auth)/actions.ts、proxy.ts。
1. 复制前检查
找出以下信息,并用一两条语句告知用户:
- 技术栈:FastAPI(在 pyproject/requirements 中查找
fastapi)、Next.js(在 package.json 中查找next)或其他 Node 服务器(Express、Hono、Fastify、纯http)。 - 数据库层:SQLModel/SQLAlchemy、Drizzle、Prisma 或原始 SQL,以及 session 或
db对象的位置。 - 现有认证:
users表、登录路由、JWT 库、认证提供商(Clerk、Supabase、Auth.js)。如果已有认证,请停止并询问是替换还是扩展。 - 项目是否已存在包含数据的
users表。如果是,则通过迁移将模板的列映射到该表,而不是创建第二个表。
2. 复制并接入
使用插件的脚本进行复制,而不是通过读取和重写文件:脚本会精确复制文件且不消耗 token。脚本位于本技能基础目录上两级的 scripts/install.mjs(<skill-dir>/../../scripts/install.mjs)。在项目根目录下先使用 --dry-run 运行,然后正式运行:
node <skill-dir>/../../scripts/install.mjs fastapi app --tests tests # app/auth/*.py, tests/test_auth.py
node <skill-dir>/../../scripts/install.mjs nextjs . # 或者使用 src/(如果 @/ 别名指向该目录)
node <skill-dir>/../../scripts/install.mjs node src/auth # 仅核心,适用于其他 Node 服务器
如果目标文件已存在,脚本会拒绝覆盖且不复制任何内容。当冲突文件是需要合并的文件(如已有的 proxy.ts 或 middleware.ts)时,使用 --keep-existing 重新运行,该选项会复制其余文件,然后手动合并。只有在用户同意丢失文件的情况下才使用 --force。如果 node 不可用,请手动复制相同的文件(使用 cp),并且仍然不要重新输入它们。
复制后,仅按以下步骤指定的内容进行修改。保持 security.py、core.ts 和路由中的逻辑不变。
FastAPI
- 使用
install.mjs fastapi <package-dir> --tests <tests-dir>复制(例如app/auth/)。 - 编辑
auth/db.py,将get_session改为项目现有的 session 依赖项。这是 auth 接触数据库设置的唯一位置。 - 如果项目使用纯 SQLAlchemy 而非 SQLModel,将
models.py中的User重写为具有相同列的 SQLAlchemy 模型,并保留 Pydantic 模式。 - 在应用主文件中调用
app.include_router(auth_router)。 - 使用
user: CurrentUser或dependencies=[Depends(require_role("admin"))]保护路由。 - 添加依赖项:
pyjwt、pwdlib[argon2,bcrypt]、email-validator、python-multipart、sqlmodel(如果尚未存在)。 - 通过项目的迁移系统创建
users表(如果使用 Alembic,则使用自动生成)。 - 修复复制的
test_auth.py中的导入,指向正确的包路径(例如将from auth改为from app.auth),然后运行测试。
Next.js(App Router)
- 使用
install.mjs nextjs <app-root>复制:核心及其测试、lib/auth/*、app/(auth)/actions.ts和proxy.ts。 - Next.js 15 或更早版本:将
proxy.ts重命名为middleware.ts,并将其导出重命名为middleware。如果项目已存在中间件/代理文件,则将认证检查合并到其中。 - 将
lib/auth/users.ts指向项目的数据库:修改db导入,或为其五个函数重写以适配 Prisma/原始 SQL。将schema.ts合并到现有的 Drizzle 模式中并生成迁移。 - 将代理中的
PROTECTED设置为应用的私有路径。 - 使用项目自身的组件和样式构建
/sign-in、/sign-up、/forgot-password和/reset-password页面。每个页面都是一个表单,通过useActionState将请求提交到对应的服务器动作;在登录页面上将next作为隐藏字段传递,在重置页面上传递token搜索参数。 - 在服务器组件和动作中,使用
lib/auth/session.ts中的getUser()或requireUser("admin")。 - 依赖项:
jose、bcryptjs、zod、server-only(如果按原样使用 Drizzle 文件,则还需要drizzle-orm)。
其他 Node 服务器(Express、Hono、Fastify、纯 http)
仅使用 install.mjs node <dir> 复制核心。以项目风格编写路由,保持与 templates/nextjs/app/(auth)/actions.ts 相同的行为:注册、登录(未知邮箱和错误密码返回相同的错误信息;即使未找到用户也要调用 verifyPassword)、注销、获取当前用户、修改密码、忘记密码(无论账户是否存在都返回相同回复)、重置密码(使用 readResetToken 并传入用户当前的哈希值)。从 session cookie(使用 cookieOptions() 设置)或 Authorization: Bearer 头中读取令牌。添加 requireUser/requireRole 中间件。
3. 环境配置
将以下内容添加到 .env.example(切勿添加到已提交的 .env 中):
AUTH_SECRET– 至少 32 个随机字符。使用node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"为用户生成本地.env的值;切勿在聊天中打印。AUTH_ACCESS_TOKEN_MINUTES(默认 7 天),AUTH_RESET_TOKEN_MINUTES(默认 60)。- FastAPI:
FRONTEND_URL,以及用于重置密码邮件的SMTP_HOST、SMTP_PORT、SMTP_USER、SMTP_PASSWORD、EMAIL_FROM。Next.js:APP_URL,然后将lib/auth/email.ts的主体替换为项目的邮件提供商。 如果未配置邮件,重置链接会被记录到日志中,这对于本地开发来说是可以接受的。
4. 检查是否正常运行
运行复制的测试以及项目自身的检查(测试、类型检查、代码检查、构建)。报告失败信息及其输出。然后告知用户他们仍需自行完成的工作,通常包括:在生产环境中设置 AUTH_SECRET、配置邮件、在真实数据库上运行迁移。
规则
- 保留:Argon2/bcrypt 哈希、针对未知邮箱的虚拟哈希检查、未知账户返回相同回复、重置令牌与密码哈希绑定、令牌的
purpose检查、httpOnly SameSite=Lax Cookie、重定向时的safeNext。 - 不要将令牌存储在 localStorage 中,不要记录密码或令牌,不要为认证路由放宽 CORS。
- 模板中不包含登录频率限制。如果项目已有频率限制器,请将登录和忘记密码路由放在其后;如果没有,请提及此点。
- 会话是签名令牌,因此注销只会结束当前浏览器中的会话,但复制的令牌在过期前仍然有效。如果用户需要“全局注销”,请添加一个
token_version列,并在令牌读取器中检查它。