mcpField
G
genesis-auth

genesis-auth

github.com/lwlee2608安全145 次安装5 天前更新
代码仓库

关于 genesis-auth

genesis-auth 是为现有 genesis 项目添加身份验证代码的技能,会依据项目结构和需求实现方案。它提供从种子管理员登录到 MFA 与审计日志的三个安全级别。

主要功能

  1. 01basic、standard 和 strict 级别
  2. 02Cookie 与服务端会话
  3. 03可选 Google 和 Apple SSO
  4. 04密码重置与角色检查
  5. 05MFA、速率限制和审计日志

适用场景

  1. 01为 genesis 服务端添加身份验证
  2. 02按应用敏感程度选择验证方案
  3. 03支持浏览器及移动端/API 使用者
  4. 04扩展现有数据库项目的身份验证

安装

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

$npx skills add https://github.com/lwlee2608/genesis --skill genesis-auth

安装后在 Claude Code 中输入/genesis-auth确认已加载。

详细介绍

genesis-auth

为 genesis 项目添加身份验证。用户选择一个级别并说明需求;此技能会推导出合适的机制——绝不询问用户选择 JWT 还是 Cookie 等实现细节——然后直接将代码写入目标项目。

此技能是一份指南,而不是照搬任务。没有可供克隆的参考实现:请阅读目标项目现有代码,并编写与之匹配的身份验证代码。

前提条件: 服务端需要 genesis DB 层——包含 goose 迁移、sqlc 和 users 表的 internal/db。genesis CLI 不会生成该层。若缺少此层,请停止并告知用户先通过 /genesis sqlc 添加它。

级别

级别使用场景包含内容
basic内部工具从环境变量预置单个管理员,使用密码登录,并在 Postgres 中保存 Cookie 会话。不支持注册或电子邮件。
standard常规应用支持电子邮件+密码的用户,并验证电子邮件;可选 Google/Apple SSO;在 Postgres 中保存会话;支持密码重置和管理员/用户角色。
strict敏感数据在 standard 基础上增加 TOTP MFA、速率限制和临时锁定、权限变更时轮换会话,以及审计日志。除此之外,建议使用外部 IdP(Keycloak、Auth0、WorkOS),而不是继续编写更多自定义代码。

提问流程

  1. 先阅读参数。 basic/standard/strict 用于确定级别;google/apple 用于确定 SSO。只询问尚未确定的内容。

  2. 在一次 AskUserQuestion 调用中询问所有剩余问题,并将推荐选项放在首位,标注为“(推荐)”:

    • 级别:basic | standard (Recommended) | strict
    • 客户端:browser only (Recommended) | also mobile/API consumers
    • SSO 提供方(multiSelect):google | apple——不选择任何选项表示不使用 SSO。

    basic 仅支持浏览器,不支持 SSO:如果参数中已指定 basic,则跳过客户端和 SSO 问题;如果用户在同一次调用中选择 basic,则忽略这两项的回答。如果参数将 basic 与某个提供方组合在一起,请在确认时指出冲突。

  3. 推导机制——不要询问用户:

    • 仅浏览器 → 使用 Cookie(HttpOnly、Secure、SameSite=Lax)+ 在 Postgres 中保存服务端会话令牌。Web 应用通过 Vite 代理 / nginx 与 API 使用同源通信,因此不添加 CORS。跨站 GET 请求仍会发送 Lax Cookie:避免通过 GET 更改状态,并拒绝来源为外部 Origin 的 Cookie 身份验证变更请求。
    • 移动端/API 使用者 → Web 端仍使用相同的 Cookie 流程,此外,移动端使用来自同一会话表的不透明持有者令牌,机器使用者使用 API 密钥。不要使用 JWT:用户登出、重置密码或更改角色时,JWT 无法撤销。
  4. 用文字确认推导出的方案,不要再提供选择器。 示例:“basic 级别:预置管理员、在 Postgres 中保存 Cookie 会话、无 SSO、仅服务端(无 Web 登录界面)——继续吗?”如果用户要求更改机制(例如“其实要用 JWT”)或要求提供 Web UI,请说明相应的权衡,并按用户要求执行。

实现规则

  1. 开始编写前,先阅读目标项目。 项目的路由器、配置结构体、迁移编号和包布局决定新增代码的结构。请遵循现有项目,不要照搬本文档中的布局。
  2. 扩展现有的 users 表,不要另建一张表。 genesis 服务已包含 internal/db/migrations/0001_create_users.sql,其中有唯一的 username、password_hash 和 user_role 枚举。请在新的编号迁移中添加列和新表。对于 standard 及以上版本,添加以小写形式存储的唯一 email,使用 email 登录,并在注册时将 username 设为该 email。对于已有数据的表,切勿假定用户名就是 email:在强制设为 NOT NULL 前先回填,并将缺少地址和大小写冲突的情况告知用户,不要擅自猜测。
  3. 遵循 genesis 服务的既定布局:
    • internal/auth/ — 密码哈希、会话/令牌签发与验证、身份提供方客户端。此处不得包含 gin 类型。
    • internal/api/http/handler/auth.go — 登录、登出、注册、重置端点。
    • internal/api/http/dto/auth.go — 请求/响应结构体。
    • internal/api/http/middleware/auth.go — 会话/Bearer 验证、角色检查。
    • internal/db/migrations/NNNN_*.sql — goose -- +goose Up / Down 块,包含正向和反向迁移。
    • internal/db/queries/*.sql — sqlc 命名查询;编辑后运行 make generate(make dep 会安装 sqlc)。
  4. 接好所有组件。 在 SetupRoute 中注册处理器和中间件,将任何新依赖添加到 Services 结构体,并在 main.go 中构造。只编译成功却从未挂载的 Auth 代码并不算完成。
  5. 通过现有机制配置。 在 internal/auth 中定义 auth.Config,并像 db.Config 一样将其组合到 cmd/<app>/config.go 的结构体中。在 application.yml 中设置非机密默认值,并使用 . → _ 大写形式,将所有键写入 .env.example(auth.sessionTtl → AUTH_SESSIONTTL)。请勿将机密(种子密码、客户端密钥、SMTP 密码、密钥)放入 application.yml,并为其添加 mask:"true" 标签:加载器会在调试级别(默认级别)输出整个配置。遵循加载器的字段绑定方式(参阅 adder 技能);切勿直接读取 os.Getenv。
  6. 优先使用标准库和现有依赖。 密码使用 golang.org/x/crypto/bcrypt,令牌使用 crypto/rand。只有当对应版本确实需要时(OIDC、TOTP)才添加依赖,并运行 go mod tidy。
  7. 切勿记录或返回机密。 不得在日志或错误响应中包含密码、哈希值、会话令牌或重置令牌。会话、重置、验证和 API 令牌只存储 SHA-256 哈希值(32 字节,由 crypto/rand 生成);bcrypt 仅用于密码,因为令牌哈希必须可通过索引查找。不得透露账户是否存在:未知用户和密码错误时返回相同错误(与虚拟哈希进行比较,以匹配耗时),并对所有重置请求返回相同响应。
  8. 以原子方式重置。 在一个事务中验证/消费重置令牌、更新密码并撤销会话。对令牌加锁或通过条件消费,确保并发请求不能同时成功。
  9. 所有时间戳列均使用 TIMESTAMPTZ。 genesis 的 users 表已使用该类型(created_at、updated_at),sqlc 会将其映射为 pgtype.Timestamptz。会话/重置的过期时间和生命周期列也应如此;切勿混用普通 TIMESTAMP,它会丢失时区偏移,并导致在非 UTC 数据库上进行过期检查时出错。
  10. 过期不等于清理。 接入有界的定期任务,删除已过期的会话以及已过期/已使用的重置记录,并添加合适的索引。
  11. 验证 bcrypt 的字节数限制。 注册/重置时,拒绝超过 72 字节的密码,并返回客户端验证错误;只验证字符数是不够的。
  12. 通过 internal/auth 中的 Mailer 接口发送邮件,并提供 SMTP 实现。未配置 SMTP 时,重置和验证请求应返回 503,且不得写入令牌记录;绝不能将链接写入日志来代替实际投递。启动流程不得依赖日志级别。
  13. SSO。 使用 golang.org/x/oauth2 + github.com/coreos/go-oidc/v3;检查 state、PKCE 和 nonce,并验证 ID 令牌。身份应以独立表中的 (provider, subject) 为键,绝不能以 email 为键。仅 SSO 用户的 password_hash 必须允许为 NULL。只有双方的 email 都已验证时,才能关联到现有用户——否则,攻击者预先注册受害者的 email 后就能保留访问权限。Apple 会以跨站方式提交回调(form_post),因此其 state cookie 需要 SameSite=None; Secure;其客户端密钥是有效期最长 6 个月的 ES256 JWT,因此应在运行时使用 .p8 密钥生成;Apple 仅在首次登录时发送用户姓名。
  14. 在每个版本中都从配置种入第一个管理员。 仅当不存在 Admin 用户时才创建,绝不覆盖已有管理员;如果不存在管理员且种子密码为空,则以明确错误终止启动。注册始终创建 User;绝不接受请求中的 role。
  15. 严格处理额外要求。 在 Postgres 中保存速率限制和锁定状态(内存存储在多副本部署中会失效),并将 gin 的受信任代理设为实际代理链——gin 默认信任所有代理,因此 ClientIP() 读取的 X-Forwarded-For 可被伪造。锁定必须会过期并逐步退避;永久锁定会让任何人都能锁住管理员账户。TOTP 密钥应加密后静态存储,拒绝重复使用的验证码,并对恢复码进行哈希。

验证流程

  1. 目标服务中的 make build 成功通过。
  2. make generate 执行后无变更,且生成的代码已纳入代码树。
  3. 代码查询的每个新表或新列都有迁移文件,包含 Up 和 Down。
  4. 每个新增的配置键都出现在 .env.example 中;非机密配置键还要出现在 application.yml 中,机密字段则要带有 mask:"true"。
  5. 对于 Cookie 会话:Cookie 设置了 HttpOnly、Secure 和 SameSite。
  6. 会话令牌以哈希形式存储,包含过期时间列,且登出时会删除对应行。
  7. 实际运行验证——构建成功或显示 [no test files] 并不算验证。启动项目的 docker-compose Postgres,将服务器的 LOG_LEVEL=info 设置为 info 后运行,并用 curl 测试各流程:登录、登出、受保护的路由、角色检查。分别在全新数据库和已有用户的数据库上执行迁移(现有用户仍应能登录),并在执行 ALTER DATABASE ... SET timezone = 'Asia/Singapore' 后再次检查过期行为。
  8. standard+:使用同一个令牌并发重置 2 次时,恰好只有一次成功;重置失败时会回滚;拒绝 40 × é(80 bytes),并返回 4xx;过期行会被清理。

需要留意的常见错误

  • 重新询问已经通过参数回答的问题。 /genesis-auth basic 除最终确认外不应询问任何问题。
  • 迁移缺少 Down 区块,或修改已应用的迁移,而不是新增迁移。
  • 手动编辑 internal/db/sqlc/。 该目录中的代码由工具生成;应修改 .sql 查询并重新生成。

评论

支持 Markdown