ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Civitai Scoped Token 与 OAuth 授权服务器:位掩码权限模型、tRPC 强制校验与 OAuth 2.1 端点全流程

Civitai Scoped Token 与 OAuth 授权服务器:位掩码权限模型、tRPC 强制校验与 OAuth 2.1 端点全流程 Civitai Scoped Token 与 OAuth 授权服务器:位掩码权限模型、tRPC 强制校验与 OAuth 2.1 端点全流程【免费下载链接】civitaiA repository of models, textual inversions, and more项目地址: https://gitcode.com/GitHub_Trending/ci/civitai本文以 Civitai 仓库中的 OAuth Scoped Tokens 实施清单(docs/auth/oauth-scoped-tokens-checklist.md)为主线,完整讲解该项目如何把从未被强制执行的 API Key 权限改造成一套真正的细粒度权限体系:25 个位掩码 Scope 的定义与预设组合、tRPC 中间件的强制校验链路、基于node-oauth/oauth2-server的授权码/PKCE 授权服务器,以及设备授权流、撤销端点、速率限制与审计日志等安全工程细节。读完后你将掌握:如何设计一套兼容存量 API Key 的位掩码 Scope 系统、如何在 tRPC 层面做到未标注端点对受限 Token 默认拒绝(fail-safe),以及如何组织 OAuth 各端点与 Redis/数据库的存储策略。背景:权限已存在但从未被强制执行Civitai 原有的 API Key 体系在数据库中定义了KeyScope枚举(Read/Write/Generate),但没有任何中间件或 tRPC 过程会拿这个值做校验——任何 API Key 都能做该用户能做的全部事情。设计文档(oauth-scoped-tokens.md)明确指出这一现状,并说明早期 PR #1313 曾启动 OAuth 工作但被搁置,其分支虽已无法直接合并,但架构决策(授权码存 Redis、Token 存为ApiKey行、选用node-oauth/oauth2-server)被保留为参考。该 PR 同时留下了一批必须规避的已知问题:client secret 从不校验、无 PKCE、scope 校验被注释掉、Redis 过期时间设置在了原始 code 字段而非哈希后的 key 上、allowEmptyState: true导致 CSRF 风险、同意页直接展示裸client_id、token 响应携带用户 PII 等。清单文档正是围绕如何从零重建并真正落地强制执行展开,分为四个阶段:Scoped Token 强制执行、OAuth 服务器、已连接应用管理、高级流程与集成,外加一节来自安全审计的加固项。Phase 1:Scoped Token 强制执行TokenScope:25 个位掩码 Scope 与 Full 复合值清单 1.1 要求创建src/shared/constants/token-scope.constants.ts,内容为一个位运算枚举:TokenScope的全部 25 个基础 Scope 都是 2 的幂,另加一个Full复合值(1 25) - 1(即 33554431,所有位全置 1)。完整定义如下(引自配套设计文档 oauth-scoped-tokens.md):enum TokenScope { None 0, // Account Profile UserRead 1 0, // 1 — Read own profile, settings, preferences UserWrite 1 1, // 2 — Update profile, settings, preferences // Models Resources ModelsRead 1 2, // 4 — Browse, search, download models ModelsWrite 1 3, // 8 — Upload, edit, publish, unpublish models ModelsDelete 1 4, // 16 — Delete own models // Media Posts (images, videos, posts — tightly coupled) MediaRead 1 5, // 32 — View images, videos, posts, galleries MediaWrite 1 6, // 64 — Upload images/videos, create/edit posts MediaDelete 1 7, // 128 — Delete own media/posts // Articles ArticlesRead 1 8, // 256 — Read articles ArticlesWrite 1 9, // 512 — Create/edit articles ArticlesDelete 1 10, // 1024 — Delete own articles // Bounties (write implicitly allows buzz spend for bounty creation) BountiesRead 1 11, // 2048 — View bounties and entries BountiesWrite 1 12, // 4096 — Create/edit bounties, submit entries BountiesDelete 1 13, // 8192 — Delete own bounties // AI Services (generation, training, scanning — all orchestrator requests) AIServicesRead 1 14, // 16384 — View generation/training history AIServicesWrite 1 15, // 32768 — Generate, train, scan via orchestrator // Buzz (Currency) BuzzRead 1 16, // 65536 — View buzz balance and transaction history // Collections Interactions CollectionsRead 1 17, // 131072 — View own collections CollectionsWrite 1 18, // 262144 — Create/edit collections, add/remove items SocialWrite 1 19, // 524288 — Follow, react, comment, review SocialTip 1 20, // 1048576 — Tip other users (buzz spend for tips) // Notifications NotificationsRead 1 21, // 2097152 — Read notifications NotificationsWrite 1 22, // 4194304 — Mark read, update preferences // Vault VaultRead 1 23, // 8388608 — View vault contents VaultWrite 1 24, // 16777216 — Add/remove vault items // Convenience composites Full (1 25) - 1, // All bits set — full access }关键设计决策值得强调:Buzz 消费是隐式的,不设独立的BuzzSpendscope:AIServicesWrite隐含生成/训练/扫描的 buzz 开销,BountiesWrite隐含悬赏创建开销,打赏则单独立SocialTipscope;Full是单一值而非逐枚枚列举,用作存量 Key、会话认证、内部生成 Key 的默认值;25 个位占用 32 位整数中的 25 位,预留 7 个位用于未来扩展,新增 scope 只需加一个新位并更新Full;选择位掩码而非数组,是为了复用仓库中既有的Flags工具类(提供hasFlag、addFlag、intersects等位运算,此前已用于 NSFW 级别等系统)。配套要求还包括:一套人类可读的 label map(供 UI 显示),以及 scope 到资源表 UI 列的映射(Read / Write / Delete 三组)。当前源码状态:仓库中的 token-scope.constants.ts 如今是一个 re-export shim,把定义统一收敛到civitai/auth包(即 packages/civitai-auth/):注释说明常量已迁移到该包,使集中认证 hub(负责 OAuth 同意页与 scope 校验)和主应用共享同一份位掩码/标签定义——fork 一份位掩码定义是潜在的安全/正确性 bug。现有调用方仍从~/shared/constants/token-scope.constants导入,接口不变。同一目录下存在 token-scope.constants.test.ts 对常量行为做测试覆盖。预设组合(Read Only / Creator / AI Services / Full Access)清单要求提供四个 Scope 预设常量,它们只以代码常量形式存在、不落库:预设组成 Flags典型用途Read OnlyUserRead \| ModelsRead \| MediaRead \| ArticlesRead \| BountiesRead \| BuzzRead \| CollectionsRead \| AIServicesRead \| NotificationsRead \| VaultRead分析、仪表盘CreatorRead Only ModelsWrite \| MediaWrite \| ArticlesWrite \| BountiesWrite \| CollectionsWrite \| SocialWrite发布工具AI ServicesAIServicesWrite \| AIServicesRead \| BuzzRead生成/训练 AgentFull AccessFull个人自动化数据库迁移:tokenScope 列与向后兼容清单 1.2 的迁移策略核心是默认即 Full,存量零破坏:给ApiKey表新增tokenScope Int default(33554431)列,默认值就是Full;依赖 NOT NULL DEFAULT 让所有存量ApiKey行自动回填为Full,避免逐行 UPDATE;同时新增lastUsedAt DateTime?列(供 1.9 的使用频率跟踪);旧的scope KeyScope[]列暂时保留,延后到 Phase 1.8 再清理;先在 dev/staging 跑迁移验证无破坏。选择默认 Full而非默认 None的原因(设计文档明确):开发期间若有新 Key 打在生产数据库上,Full 默认值保证其行为与旧系统一致,不会因忘记显式设 scope 而把服务打挂。Scope 强制中间件:fail-safe 是核心安全属性清单 1.3 定义了强制执行链路:扩展 tRPC meta 类型,增加requiredScope: number字段;在 tRPC 入口(清单标注为src/server/trpc.ts)创建 scope 校验中间件:读取ctx.tokenScope位掩码,执行Flags.hasFlag(tokenScope, procedure.requiredScope),缺失即返回带清晰错误信息的 403;会话认证(NextAuth cookie)一律按Full处理,浏览器端零感知;fail-safe:对未标注requiredScope的端点,受限 Token 一律拒绝(会话不受影响)。清单特别记录了一个演进过程:fail-open 漏洞被识别并修复(现在 fail-safe)——最初版本对未标注端点是放行的,这会让任何一个漏标注的端点变成受限 Token 的提权通道;getSessionFromBearerToken()扩展为从ApiKey记录加载tokenScope,并把它挂到 tRPC context 上。源码互证:当前仓库的 bearer-token.ts 完整实现了第 5 点及其延伸。getSessionFromBearerToken 先对原始 key 做generateSecretHash(SHA-512 加盐哈希)再查库,select字段包含tokenScope、buzzLimit、lastUsedAt、clientId;查不到即返回 null。此外源码还体现两处清单之外但同等重要的行为:被 ban 的用户在 bearer 路径被集中拒绝(L43,注释说明必须在这里拦,防止某个忘记复查的/api/v1handler 让被 ban 用户的 OAuth Token 继续工作);以及 OAuth 签发 Token 的 subject 解析(L49-L61):带clientId的 Token 以(userId, clientId)的 consent 记录作为稳定身份(跨 access token 轮换不变),其buzzLimit从OauthConsent读取;普通 API Key 则用自身行 id 与行上buzzLimit。可以推断这是清单 2.14per-key 消费上限落地后的演进——OAuth Token 的上限随 consent 管理,而非绑定单个 token 行。全量标注约 767 个 tRPC 过程清单 1.4 是工程量最大的一步:全部 83 个 router、约 767 个过程逐一标注.meta({ requiredScope: TokenScope.X }),且从第一天起全量覆盖而非增量补标。标注工作由 3 个外部模型(Gemini 2.5 Pro、Gemini 3.1 Pro、GPT 5.1 Codex)交叉评审,正是在这次评审中发现了前述 fail-open 漏洞。一个典型提权修复:user.getToken(用户自助铸造新 API Key 的过程)被提升到Fullscope——否则持有限制 Key 的调用方可以给自己铸造新的 Key,绕过 scope 限制。内部 Key 审计与/api/v1/me扩展清单 1.5 要求审计所有程序化创建 Key 的位置(addApiKey调用点)。结论是:隐藏的内部生成/编排器 Key 全部使用type: Systemscope: [Generate],它们通过 DB 列默认值自动获得FulltokenScope,无需任何代码改动——这正是默认 Full策略的回报。审计覆盖的调用方包括orchestrator-key.ts、get-orchestrator-token.ts及两个admin/orchestrator/*端点(后者后来已被删除)。清单 1.6 修改了/api/v1/me端点:当请求经 scoped API Key 认证时,响应追加tokenScope(位掩码)字段;经 API Key 认证时追加buzzLimit。设计文档给出了响应形态:{ id: 123, username: user, tier: member, status: active, isMember: true, subscriptions: [gold], tokenScope: 33554431, buzzLimit: { daily: 5000, weekly: null, monthly: 50000 } }这是编排器(orchestrator)侧强制的入口:它用 API Key 作为 bearer token 调/api/v1/me,拿到tokenScope后可自行执行Flags.hasFlag(tokenScope, ...)判断,并对buzzLimit做消费上限控制。由于 OAuth access token 本身就是ApiKey行,它们对编排器透明可用,无需特殊处理。API Key 界面改造与延后清理清单 1.7 更新了 API Key 管理 UI:ApiKeyModal.tsx用预设下拉 权限表替换旧的多选框——预设选中后自动填充 checkbox,用户可在此基础上逐格自定义;ApiKeysCard.tsx为每把 Key 显示 scope 摘要徽章与最近使用时间;addApiKey变更与api-key.schema.ts校验同步支持新的位掩码格式。可选的过期日期选择器被明确延后(nice to have,未勾选)。清单 1.8 是刻意延后的清理项,直到生产验证通过:删除旧scope KeyScope[]列、删除KeyScope枚举、清理 service/controller 中的旧引用、更新相关测试。在清单中这四项均保持未勾选状态,与旧列暂留的迁移策略互相印证。lastUsedAt 跟踪:一小时防抖的 fire-and-forget清单 1.9 要求跟踪每把 Key 的最近使用时间,并展示在 Key 列表 UI 中。实现约束是防抖更新——每把 Key 至多每小时一次,fire-and-forget。源码完全对应: bearer-token.ts L8 定义LAST_USED_DEBOUNCE_MS 60 * 60 * 1000,在 L29-L31 中,当lastUsedAt缺失或距今超过一小时时,以.catch(() {})方式异步写回,不阻塞认证主路径——高频调用场景下避免每次请求都产生一次 DB 写。Phase 2:OAuth 服务器依赖与数据库设计清单 2.1 引入node-oauth/oauth2-server并验证 Node.js 版本兼容性。2.2 定义了两张新表,列结构在清单中逐项列出:OauthClient(OAuth 应用注册表):列类型/约束idTEXT 主键(UUID)secretTEXT(哈希存储;公共客户端可空)name/descriptionTEXTlogoUrlTEXT,可空redirectUrisTEXT[](精确匹配的回调 URI 集合)grantsTEXT[](如authorization_code、refresh_token、client_credentials)allowedScopesInt 位掩码(该客户端可申请的上限)isConfidentialBoolean(公共/机密客户端)userIdInt 外键 → User(注册开发者)isVerifiedBoolean,默认 false(官方审核后展示 Verified 徽章)createdAt/updatedAt时间戳OauthConsent(同意记录):idSerial 主键、userIdInt 外键、clientIdTEXT 外键、scopeInt(已同意 scope 的位掩码)、时间戳,以及(userId, clientId)唯一约束。此外:ApiKeyType枚举新增Access、Refresh两个值(保留原有System、User);ApiKey表新增clientId TEXT?外键列,标记该 Token 由哪个 OAuth 客户端签发(用户自建 Key 为 null)。从当前源码看,src/server/auth/bearer-token.ts中apiKey.clientId与oauthConsent.buzzLimit的读取逻辑说明上述列与关系确实已在生产代码中生效。OAuth 模型:十个方法与三条时间参数清单 2.3 要求实现src/server/oauth/model.ts(以清单记载的路径为准),包含十个模型方法:getClient(clientId, clientSecret)— 取客户端,机密客户端必须校验 secret 哈希(针对 PR #1313secret 从不校验的修复);saveAuthorizationCode(code, client, user)— 授权码存 Redis,key 为哈希值,过期时间正确设置;getAuthorizationCode(code)/revokeAuthorizationCode(code)— 按哈希 key 读写;saveToken(token, client, user)— 创建 Access Refresh 两条ApiKey行,token 哈希存储,设置 scope 位掩码;getAccessToken(accessToken)/getRefreshToken(refreshToken)— 按哈希 token 查ApiKey,并校验 type 分别为 Access/Refresh;revokeToken(token)— 删除ApiKey行,并联动吊销关联的 access token;validateScope(user, client, scope)— 把请求的 scope 与客户端allowedScopes求交校验;verifyScope(token, scope)— 通过Flags.hasFlag()校验 token 自身 scope 位掩码。三条硬参数:OAuth token 统一加civitai_前缀(便于在日志/滥用排查中区分);access token 寿命1 小时(PR #1313 是 7 天,被刻意缩短);refresh token30 天;授权码10 分钟。当前仓库src/server/oauth/目录保留了 audit-log.ts 与 user-code.ts(设备流 user code 工具),各端点则收敛在 src/pages/api/auth/oauth/[...path].ts 这一统一路由中——从源码结构看,实现已从清单阶段的一方法一文件组织方式整合到了按路径分发,但方法语义(哈希 key、Redis 存储、ApiKey 行)在清单中已定死。授权端点、同意页与 Token 端点清单 2.4 要求实例化OAuth2Server时设置allowEmptyState: false(直接封死 PR #1313 的 CSRF 缺口),PKCE 仅接受 S256 并在发放授权码前校验。授权端点(src/pages/api/auth/oauth/authorize.ts,清单记载路径):要求 NextAuth 会话认证;校验client_id、redirect_uri(精确匹配注册值)、response_typecode、scope、state;校验 PKCEcode_challenge与code_challenge_methodS256;查OauthConsent——该用户此前已同意过相同 clientscope 则跳过同意页,否则携带查询参数跳转同意页;同意审批时若勾选记住,落库 consent 记录。同意页(src/pages/login/oauth/authorize.tsx):按client_id拉取应用详情(名称、logo、描述,绝不展示裸 client_id);用tokenScopeLabels把请求的 scope 渲染成人类可读列表;isVerified时展示 Verified by Civitai 徽章;语义为全有或全无——用户要么接受全部请求 scope,要么整体拒绝;提供记住此决定复选框;批准时以表单 POST 回授权端点并携带approvedtrue(CSRF 安全);拒绝时重定向回客户端并附erroraccess_denied;未登录用户先跳登录再回到同意流程。Token 端点(src/pages/api/auth/oauth/token.ts):处理grant_typeauthorization_code(校验 code PKCEcode_verifier)与grant_typerefresh_token(校验并轮换refresh token);机密客户端经模型校验 secret;响应仅含{ access_token, token_type, expires_in, refresh_token, scope },不返回任何用户 PII(针对 PR #1313 缺陷 #7)。UserInfo 与撤销端点UserInfo(userinfo.ts):要求有效 access token 且具备UserReadscope,仅返回{ sub, id, username, image }。安全加固一节还记录了:userinfo.ts采用 fail-safe 策略——scope 缺失时默认为 0 而非 Full。撤销端点(revoke.ts,RFC 7009 合规):接受tokentoken_type_hint(access_token 或 refresh_token);删除前要求认证(会话或客户端凭据)并验证调用方拥有被撤销的 token;删除ApiKey行;撤销 refresh token 时连带吊销其全部关联 access token;无论 token 是否存在一律返回 200(RFC 7009 要求,避免枚举探测);速率限制按 IP 而非 client_id 计算,防止伪造 client_id 绕过限额。Redis 存储、开发者门户、速率限制与审计日志Redis(2.10):在 Redis 客户端中新增OAUTH.AUTHORIZATION_CODESkey 常量;授权码存为 Redis hash——key 是哈希后的 code,value 是 JSON(含 client、user、scope、PKCE challenge、redirectUri),过期时间设置在该哈希 key 上。清单明确标注这是避开 PR #1313 缺陷 #4(过期设置在原始 code 字段而存储用哈希 key,导致授权码永不过期);开发者门户(2.11):新增oauth-clienttRPC router,提供create(生成 ID secret)、getAll、getById、update(名称/描述/redirectUris/allowedScopes)、rotateSecret(重新生成并哈希存储)、delete(级联删除关联 token 与 consent)六个过程;账户页以OAuthAppsCard呈现:应用列表、带 scope 选择器的注册新应用表单、编辑/轮换 secret/删除操作、client ID secret 一次性展示并配复制按钮;速率限制(2.12):token 端点 20 req/min / client_id;授权端点 10 req/min / 用户;撤销端点 20 req/min / client_id;响应携带X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset、Retry-After头;审计日志(2.13):OAuth 事件以结构化 JSON 输出到 stdout(供 Axiom 等日志聚合系统),覆盖client.created/updated/deleted/secret_rotated、authorization.granted、token.issued/refreshed/revoked事件类别;CORS(2.15):token 端点经addCorsHeaders放行宽松 CORS(浏览器前端无服务端,必须),userinfo 与撤销端点同样配置;按客户端的 origin 白名单限制列为未来工作。Per-Key 消费上限(buzzLimit)清单 2.14 是半完成状态,值得原样呈现:buzzLimit JSONB列已加入ApiKey表(迁移完成)、bearer 认证管线已加载 buzzLimit、/api/v1/me响应已包含 buzzLimit 供编排器强制;而Key 创建/编辑弹窗中的消费上限 UI、Redis 计数器按 Key 记账并在周期边界重置、buzz 交易中间件内强制执行三项均未勾选。源码侧 bearer-token.ts 已从 api-key.schema.ts 引入BuzzLimit类型参与会话构造,证明数据通路已打通,剩余额度执行机制仍在建设中。Phase 3:已连接应用与用量管理Connected Apps 页(3.1):账户页新增ConnectedAppsCard,从OauthConsent与活跃 token 聚合出用户已授权的全部应用,展示应用名、Verified 徽章、已授予 scope 徽章、授权日期、活跃 token 数;每应用提供 Revoke Access 按钮(删除该 client 全部 token consent 记录),带确认弹窗;无已连应用时自动隐藏;Token 活动跟踪(3.2):复用 Phase 1.9 的lastUsedAt;Connected Apps 视图展示活跃 token 数;开发者门户的每应用视图展示活跃 token 数与 consent 数;开发者仪表盘(3.3):每应用统计两项——活跃 token 数、总授权次数(consent 计数)。Phase 4:高级流程与集成Client Credentials(4.1,已完成):模型实现getUserFromClient,仅限grants数组包含client_credentials的机密客户端;token scope 限定为客户端allowedScopes,主体为客户端属主;Device Authorization(4.2,已完成):四组端点——/api/auth/oauth/device(发起,发放设备码)、/api/auth/oauth/device-token(轮询)、/api/auth/oauth/device-approve(审批)、/api/auth/oauth/device-info(按 user code 查应用详情);验证页/login/oauth/device为两步式:输入 code → 审阅应用名与 scope → 批准/拒绝。安全约束:校验grants数组包含urn:ietf:params:oauth:grant-type:device_code;发起与换 token 两个环节都拿allowedScopes校验 scope;设备码存 Redis 并带 TTL。目标场景是 CLI 工具与无头 Agent。当前仓库 src/server/oauth/user-code.ts 即该流程的 user code 工具实现;Agent 委托 Token(4.3,延后):未勾选——特殊 agent token 类型与按 agent 加严的速率限制暂不实现,现阶段用标准 OAuth token 消费上限组合替代;OIDC Discovery(4.4,已完成):/api/.well-known/openid-configuration端点发布 authorization/token/userinfo/revocation/device 端点 URL,以及支持的 scopes、grant types、response types、code challenge methods;开发者文档(4.5):综合开发者指南覆盖 OAuth 概览、应用注册、授权码 PKCE 带代码示例的完整走查、各 scope 的位掩码数值与常用组合、token 生命周期(access/refresh/撤销)、UserInfo、设备授权流、Client Credentials、速率限制与安全最佳实践。文档主体已在仓库中(oauth-developer-docs.md),清单中发布为站内静态页一项仍未勾选。安全加固:审计发现与残留项清单最后两节按已应用 / 残留(低危)组织,是全文最浓缩的安全工程总结,完整保留如下。已应用(来自多轮审计):fail-safe 中间件——未标注端点对受限 token 一律拒绝;同意绕过封死——approvedtrue仅接受 POST 提交;redirect URI 使用前对照注册值校验;scope 缺失/非法时默认0(而非 Full);负数与溢出 scope 值被拒绝;模型与撤销流程使用常量时间 secret 比较(crypto.timingSafeEqual);设备流校验 grants 数组并以allowedScopes约束 scope;撤销要求认证且按 IP 限速;user.getToken要求 Full scope(防限制 Key 铸造 token 提权);公共客户端可刷新 token(OAuth 2.1 合规);共享的createOAuthTokenPair辅助函数防止各处 token 签发逻辑漂移;userinfo.tsfail-safe——scope 缺失时默认 0。残留项(低危,未勾选):从OAuthAppsCard抽取ScopeSelector组件复用到ApiKeyModal;OIDCscopes_supported目前是数值键,考虑改为人类可读名;device-approve 的 CSRF(已由 SameSiteLax cookie 缓解);速率限制 TOCTOU:increxpire非原子,应改用 Lua 脚本或SET NX EX。未决事项总览与延伸阅读对照清单,当前仍开放的工作集中在三处:Phase 1.8 的旧KeyScope列/枚举清理(等生产验证)、2.14 的消费上限 UI 与 Redis 计数器执行、4.3 的 agent 委托 token,以及若干低危加固项。这些未勾选项本身构成了清晰的路线图。围绕本主题,仓库中可直接延伸阅读的材料:文档内容docs/auth/oauth-scoped-tokens-checklist.md本文主线的实施清单(四阶段 安全加固)docs/auth/oauth-scoped-tokens.md设计文档:scope 枚举、预设、数据库设计、决策表、编排器集成docs/auth/oauth-scoped-tokens-review.md方案评审记录docs/auth/oauth-developer-docs.md面向第三方开发者的 OAuth 接入指南docs/auth/oauth-provider-implementation-checklist.mdOAuth Provider 侧实施清单(scope 常量收敛至civitai/auth的背景见其 §A)src/server/auth/bearer-token.tsbearer token → 会话的认证管线(tokenScope/buzzLimit/lastUsedAt 加载)src/pages/api/auth/oauth/[...path].tsOAuth 各端点的统一路由实现src/server/oauth/audit-log.tsOAuth 事件结构化审计日志src/shared/constants/token-scope.constants.tsTokenScope 常量入口(现 re-export 自civitai/auth)从整体设计看,这套实现的一条主线是用存量基础设施承载新能力:Token 复用ApiKey表与 SHA-512 哈希管线、Scope 复用Flags位运算工具、授权码/设备码复用 Redis、权限查询复用/api/v1/me。新增的 OAuth 层只负责协议语义(授权码交换、PKCE、轮换、撤销),而所有谁是谁、能做什么的状态最终都落在既有数据模型上——这使得 OAuth access token 与手写 API Key 在全站(包括编排器直连)天然同权同级,也解释了为何clientId外键一行即可把两种 token 统一纳入subject与消费上限体系。【免费下载链接】civitaiA repository of models, textual inversions, and more项目地址: https://gitcode.com/GitHub_Trending/ci/civitai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表