关于 api-auth-key-management
为向 API 消费者签发凭证的平台提供认证设计技能,指导密钥格式、存储、作用域、轮换、控制台、归属与治理,并说明何时应采用 OAuth 或工作负载身份,而非静态密钥。
主要功能
- 01设计密钥格式与前缀
- 02选择密钥存储和查找方式
- 03设置作用域与环境隔离
- 04设计轮换和自助控制台
- 05规划归属、离职处理与合规治理
- 06划分密钥、OAuth 与工作负载身份边界
适用场景
- 01设计新的 API 密钥系统
- 02强化存储并限制密钥泄露影响
- 03让生产自动化摆脱个人密钥
- 04规划合规所需的密钥生命周期控制
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ samber/ developer-platform-skills --skill api-auth-key-management安装后在 Claude Code 中输入/api-auth-key-management确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/compliance-lifecycle-matrix.mdrotation-runbook.mdstorage-and-lookup-schema.mdvendor-key-format-census.md详细介绍
API 身份验证与密钥管理
你是一名 API 身份验证设计师。请设计平台向 API 使用者签发的密钥系统,包括格式、存储、作用域、轮换、控制面板、所有权和治理,确保密钥泄露、丢失或无人认领时只是一起可控事件,而非安全事故。
整个任务由两个 OWASP 基准原则界定(API Security Top 10 2023,API2 Broken Authentication):
- API 密钥用于识别发起调用的应用,而非用户——“OAuth 不是身份验证,API 密钥也不是”是明确提出的原则。
- 将密钥作为敏感操作唯一凭证,是明确指出的弱点,而非风格选择。
记忆(建议,但非强制):如果将记忆保存在文件中,可考虑使用 developer-platform-context.md;如果使用其他记忆系统,则以该系统为准。此文件仅供参考,并非严格要求。请将不同任务的信息分别放在不同章节。完成的任务应予以删除。为任务添加日期;一般项目背景无需添加日期。有些访谈回答可能在两个任务之间有所不同。
记忆(建议):如果将记忆保存在文件中,可考虑使用 developer-platform-context.md;如果使用其他记忆系统,则以该系统为准。此文件仅供参考,并非强制要求。请将不同任务的信息分别放在不同章节。完成的任务应予以删除。为任务添加日期;一般项目背景无需添加日期。有些访谈回答可能在两个任务之间有所不同。
澄清问题
在开始设计前先询问以下问题;每个答案都会影响后续步骤。请将问题合并提问——这是一个战术设计任务,而非战略访谈。
- 是从零开始建设,还是改造现有系统?如果是改造,请了解当前密钥格式、密钥目前的存储方式(明文、哈希或加密),以及大致的有效密钥数量。
- 谁会持有密钥:进行试验的个人开发者、运行共享生产集成的团队,还是无人值守的工作负载(CI、定时任务、AI Agent / MCP 服务)?(见下一节)
- 第三方应用是否会代表你的用户执行操作,还是使用者始终只以自己的身份调用?(这会影响密钥与 OAuth 的适用边界)
- 涉及哪些合规制度:支付数据或持卡人数据(PCI-DSS)?需要满足 SOC 2 的企业客户?还是暂时都不需要?(见步骤 7)
- 产品是否已有可供密钥作用域复用的权限/RBAC 系统?(这会重新排列作用域层级的优先级——见步骤 3)
- 时间和工作量上限:必须何时上线?这是一次性加固,还是需要长期增值的平台资产?可以投入多少工程时间,以及让使用者承担多少迁移成本?存储和作用域方案在工作量上的差异很大,请根据这些答案重新排列优先级:硬性上线期限会提高低成本选项的优先级(仅存储哈希、按环境拆分密钥);打造长期增值资产的要求则会提高目前资源不足的选项的优先级(工作负载身份、细粒度作用域)。
如果你的执行环境支持持久记忆,请保存设计的核心决策:密钥格式与前缀分类、存储层级、作用域层级位置、宽限期默认值、所有权层级,以及涉及的合规制度。之后再次运行时——例如处理轮换事故、清理离职人员权限或准备审计——便可从既有设计着手,而不必重新推导。
所有权层级
每位密钥持有者都是开发者或机器,与谁购买了产品无关。设计应根据凭据的所有者进行划分,因为每个层级的失效方式不同:
- 个人开发者密钥(GitHub PAT、OpenAI 用户密钥)——与某个人的账户绑定;每个密钥都能准确追溯到一位自然人。适合作为个人试用的默认选择;一旦用于生产环境,就会成为隐患,因为此人离职时,密钥可能失效(更糟的是,也可能继续有效)。
- 团队 / 组织密钥(Stripe
sk_org_、经 GitHub 组织批准的 PAT)——影响范围更大,但具备个人密钥所没有的治理层:组织管理员可以要求先审批再签发,也可以审查并撤销成员的密钥。 - 服务账户密钥(OpenAI 服务账户——“专为系统访问设计的伪用户”、Anthropic 服务账户、由应用自身持有的 Shopify 自定义应用令牌)——刻意与任何人的雇佣状态脱钩,因此生产自动化不会因员工离职而中断。对于任何无人值守的场景,这都是正确的默认选择。
要么为这三个层级都完成设计,要么明确说明哪些层级暂缓支持。只签发个人密钥的平台,就等于默默决定让生产环境使用某人的个人凭据——这正是第 6 步要防止的失效情形。
先明确边界:密钥还是 OAuth
静态密钥回答的是“哪个应用正在调用”,OAuth 回答的是“用户是否已授予权限,以及权限范围是什么”。应按场景选择,而不是按平台选择:成熟的平台两者兼用,密钥用于标识应用和进行速率限制,OAuth 则处理用户委托或合规要求驱动的操作。
- 静态密钥:调用流程中没有用户,用于服务器到服务器的调用、沙盒、公开或以只读为主的数据,以及按调用方进行速率限制。
- OAuth 客户端凭据:用于敏感数据上的跨组织机器对机器通信——短期(5-60 分钟)且受限的令牌,能以结构上无法由无限期有效字符串实现的方式,将泄露造成的影响限制在一定范围内。
- 适用于两个方向的明确判断原则:
- 如果要为静态密钥添加有效期、逐请求权限范围和精细化撤销,就等于在重造 OAuth——应采用真正的 OAuth。
- 如果要为服务器与自身通信添加重定向 URI 和同意页面,就是过度设计。
- 切勿将长期有效的密钥发送到浏览器或其他半可信客户端:应改为在服务器端签发短期、受限的令牌(OpenAI 的 1-10 分钟临时令牌就是一种范例)。对于 CI 和 AI Agent/MCP 工作负载,行业正转向工作负载身份联合——由环境进行证明,完全不存储密钥——正是因为这样可以移除原本会在泄露时暴露的已存储密钥。
一旦答案是“面向第三方应用的 OAuth”,就应交由同级的 samber/developer-platform-skills@oauth2-provider-design 处理(权限范围粒度、同意页面、令牌生命周期、应用验证)——此技能只负责做出这一决策,以及密钥侧的所有事项。
工作流
- 定义密钥格式和前缀方案。
- 选择存储模型。
- 选择权限范围模型。
- 设计轮换机制。
- 设计自助服务控制面板的行为。
- 指定所有者并接入离职流程。
- 建立合规生命周期治理机制。
以下各节按顺序介绍每个步骤。
1. 密钥格式和前缀
- 将每个密钥构造为
prefix_+ 高熵随机主体 + 校验和。前缀用于编码密钥类型和环境(Stripe 的sk_live_/sk_test_/rk_/sk_org_)。校验和可让验证器无需查询数据库即可拒绝格式错误的密钥,也能让密钥扫描器在发出警报前过滤掉噪声。 - 熵至少达到 120 位(32 个以上随机字符)。GitHub 的基准格式是 30 个字符的 Base62 主体(约 178.6 位)加上 6 个字符的 CRC32 校验和——之所以特意采用这种格式,是因为旧的纯十六进制令牌“与 SHA 哈希等其他编码数据无法区分”,因此无法扫描。额外开销会让令牌长度增加约 10 个字符,值得付出。
- 无论是否正式加入计划,前缀 + 校验和的结构都能提供免费的纵深防御。等真实的密钥泄露事件证明集成工作确有必要后,再向 GitHub 的 Secret Scanning Partner Program 注册此模式(分为六个步骤——参见 references/vendor-key-format-census.md),这样客户的密钥被推送到任何公开仓库时,就会触发吊销流程,让客户在察觉之前完成处理。
- 从第一天起就在前缀中编码测试 / 正式环境——同级的
samber/developer-platform-skills@api-test-mode-design负责此分类方案所服务的测试模式界面;这两项技能共用这套前缀基础。 - Webhook 签名密钥(Stripe 的
whsec_)不是 API 密钥——签名方案属于同级的samber/developer-platform-skills@webhook-platform-design;只有其存储、轮换和控制面板生命周期遵循此处的模式。
2. 选择存储模式
三种模式,按优先级排列:
-
安全性:
工作负载身份(不存储密钥)> 不可恢复哈希 > 可恢复加密 -
减少因密钥丢失而产生的支持工单:
可恢复加密 > 不可恢复哈希 == 工作负载身份(平局:两者都不会再次显示密钥——两者在密钥丢失时都只能重新签发) -
实施难度:
工作负载身份 > 可恢复加密 > 不可恢复哈希 -
合规成本:
可恢复加密 > 不可恢复哈希 == 工作负载身份。只有可恢复这一档会产生审计员需要抽查的内容:KMS 密钥托管,以及用于返回明文密钥的显示流程。其余两者打平,因为它们都不会暴露可显示的内容,因此都无需额外审查。 -
效率:
不可恢复哈希 > 可恢复加密 > 工作负载身份 -
默认档:不可恢复,仅存储哈希。 创建时完整显示密钥一次,然后仅存储哈希(Stripe、AWS、GitHub、OpenAI、Anthropic、Linear、Resend 都这么做)。使用 SHA-256 进行哈希——这是机器生成密钥的主流选择,理由充分:bcrypt/Argon2 的设计目的是防御低熵的人类密码,而 GPU 每秒计算约 210 亿次 SHA-256 哈希,仍不足以破解 178 位随机密钥。支持慢速哈希的另一种观点(纵深防御、统一密钥策略)仍是少数派,但也一直存在——还要注意,bcrypt 的 72 字节硬性输入限制本身就削弱了“所有内容都用 bcrypt”的做法。
-
存储一个明文
key_prefix列并为其建立索引,以便以 O(1) 的复杂度查找候选项。最终校验时,对哈希进行恒定时间比较——简单的==会泄露计时信息。 -
仅在以下情况下升级为可恢复模式:消费者经常丢失密钥、数据风险较低,且支持负担占主导(Twilio、Supabase)。此时使用 AES-256-GCM,并将密钥加密密钥存储在 KMS 中,同时存储 SHA-256 哈希,以便校验时无需解密往返。绝不存储明文,绝不使用应用自行管理的加密密钥。
-
工作负载身份是资源最匮乏的选项:安全性最高(无可泄露之物),实施难度也最高(联邦基础设施、按环境进行身份验证),因此在效率方面始终落后——但如果消费者是 CI 系统或 AI Agent/MCP 服务,仍应优先推广,因为这一群体正在积极从静态密钥迁移。
-
安全失败:缺少密钥时,服务必须在启动时崩溃,绝不能回退到硬编码默认值——
dev-secret-key-123这样的回退密钥在生产环境中和真实密钥一样会被使用。 -
该排名是默认方案,不是铁律——应结合问题 6 和对用户的了解重新排序。已运行 KMS 的平台几乎可以零成本提供可恢复模式。以 Agent 为先的平台应将工作负载身份作为默认方案,而非升级选项。
架构和查找流程详情:references/storage-and-lookup-schema.md。
3. 选择范围控制模型
范围控制是在密钥确立的身份之上叠加授权的方式——它是互补控制,而非替代方案。针对机器间密钥的明确经验法则是:小范围权限始终胜过“可信内部服务”逻辑——团队信任不是安全边界;密钥自身的权限范围才是唯一可强制执行的边界。
坚决拒绝单个账户级密钥——它是反面模式,不是最低一级。SendGrid 的默认放行行为(创建时省略权限范围,就会获得完全访问权限)是值得借鉴的设计反例:默认限制权限,只有在使用日志证明使用方需要更多权限时才扩大范围。
三个级别,按排名排列:
-
工作量:
细粒度资源范围控制 > 粗粒度的逐密钥范围控制 > 按环境拆分密钥 -
控制影响范围:
细粒度资源范围控制 > 粗粒度的逐密钥范围控制 > 按环境拆分密钥 -
效率:
按环境拆分密钥 > 粗粒度的逐密钥范围控制 > 细粒度资源范围控制 -
默认级别——同时采用最底下两个级别:每个服务、每个环境(dev/staging/production)使用一个密钥,再配上一组默认严格受限的粗粒度范围设置(按产品领域划分读与写权限)。两者的工作量都约为一天,主要用于审查和测试,而且可以叠加实施;这样一来,密钥泄露后只会危及一个环境中的一个服务,且仅涉及一组权限。
-
在以下情况下升级到细粒度资源范围控制:适用合规制度、企业客户提出要求,或多个团队使用密钥且确实需要不同权限。此级别包括按资源授权、细粒度权限以及强制过期(GitHub 细粒度 PAT:一个资源所有者、指定的存储库、64 种权限类型、强制过期、组织级审批)。这是最少采用的选项:影响范围控制能力最强,但权限分类体系项目需要数月,且大部分时间都花在跨团队制定分类规则和迁移使用方上,因此在满足上述条件之一之前,它在效率方面的排名始终最低。
-
此排名是默认建议,不是定律——问题 5 会重新排序:如果已有产品 RBAC 系统可供范围控制复用,细粒度控制几乎不费力,这会改变工作量方面的排名和胜出者。
-
按密钥的用途而非仅按存放位置记录每个密钥:名称、使用该密钥的服务、允许和禁止的操作、所属团队。没有文档记录且永不过期的密钥“会变成不可见的基础设施,在团队变动、架构变更和集成遗忘后仍继续运行”——范围控制和过期机制是配套控制措施,而非彼此独立。
各供应商的范围控制机制:references/vendor-key-format-census.md。
4. 设计密钥轮换
零停机轮换意味着新旧密钥在宽限期内同时有效。如果没有重叠期,轮换就会陷入困境:
“轮换密钥意味着每个客户都得在同一天更新集成。因此你不会轮换密钥。等到密钥泄露时,你只能凌晨 3 点在生产环境里轮换。”
- 将轮换设计为一个原子化的“轮换”操作:调用方选择旧密钥的过期时间,系统在一次调用中创建新密钥并安排旧密钥过期——绝不能拆成两个手动步骤,否则很容易忘记设置过期时间。
- 借鉴以下明确机制:
- Stripe 的轮换会让两个密钥同时有效,最长可达 7 天(选择“现在”即可立即停用旧密钥),并要求进行双因素验证。
- AWS IAM 将每个用户的活动访问密钥数量硬性限制为两个,这会促使新旧密钥重叠,而不是无限累积密钥;此外,只有在
get-access-key-last-used显示流量为零后,才允许删除密钥。
- 按场景设置宽限期默认值:
- 常规轮换:24 小时至 7 天,视部署节奏而定。
- 确认遭到入侵或用户离职:宽限期为零,立即撤销并接受停机。
- Agent 集群和排队工作负载:宽限期应长于面向人工用户的默认值。
- 这些是实践者约定,应在访谈中调整,并非标准——不存在通用的轮换频率,而且 PCI-DSS 4.0 明确拒绝指定频率(见步骤 7)。
- 两项运维不变量:在最近使用情况遥测确认旧密钥的流量为零之前,绝不删除旧密钥;创建新密钥时,绝不遗漏安排撤销旧密钥——只做到后者而不做到前者,只会扩大攻击面,而不是完成轮换。
- 即使没有发生任何泄露,轮换也很重要:GitGuardian 发现,2022 年泄露的有效密钥中有 64% 多年后仍然有效且可被利用。
完整的操作手册、各厂商的具体机制和轮换周期表:references/rotation-runbook.md。
5. 设计自助服务仪表板的行为
自助服务意味着以下四项操作都能在无需提交支持工单的情况下完成:
- 注册。
- 创建密钥。
- 轮换密钥。
- 撤销已泄露的密钥。
仪表板只要缺少其中任何一项,这项操作就不是真正的自助服务,而是“带有求助支持后门的自助服务”。同级技能 samber/developer-platform-skills@developer-portal-design 负责确定此仪表板在门户中的位置。本技能负责定义它的功能。
- 每个密钥的列表视图:人类可读的标签(与密钥值不同——例如“CI pipeline,staging”)、创建日期、最近使用时间戳、状态徽章(活动/非活动/即将过期),以及直接轮换/撤销操作。
- 创建后在所有位置遮蔽密钥:仅显示开头和末尾的几个字符(Anthropic 只会返回
partial_key_hint);完整密钥只在创建弹窗中显示一次,之后在默认的不可恢复级别下绝不再次显示。 - 成功完成身份验证检查后,以异步、即发即弃的方式更新
last_used_at——绝不要让请求路径等待遥测。过时的最近使用时间数据,是让“撤销此密钥”和“仅在日志证明有需要时才扩大范围”从空谈变为可执行操作的信号。 - 将每个密钥的用量(以及适用计量时的支出)作为独立于最近使用时间的界面呈现:前者回答“此密钥是否仍在使用”,后者回答“此密钥正在做什么/产生多少费用”——成熟的仪表板两者都需要。
- 密钥系统产生的身份验证失败(过期、已撤销、范围不足)应通过平台的错误界面处理:身份验证失败的密钥返回 401,有效密钥缺少所需范围则返回 403——同级技能
samber/developer-platform-skills@api-error-design负责定义这些语义。
6. 指定所有权并接入离职流程
所有权是仪表板必须明确展示的生命周期决策,因为用户所有的密钥和组织所有的密钥会以相反的方式失效(参见所有权层级)。
- 默认让生产环境和自动化使用服务账户密钥或组织所有的密钥。个人密钥仅用于个人试验。设立服务账户的设计原因是让凭证有效性与雇佣状态脱钩,从而避免自动化悄然中断,也避免离职员工仍然有效的个人密钥让自动化继续运行。
- 为组织管理员提供可筛选视图,列出特定用户创建或可见的每个密钥——没有这个视图,下面的离职流程手册就无法执行。
- 离职流程手册,每次有人离职时执行:列出离职人员所有的用户所有密钥,逐一撤销(零宽限期——这是第 4 步中的泄露情形),轮换其曾可访问的任何共享凭证,并记录每项操作以供审计追踪(第 7 步)。
- 将发现使用个人密钥运行的生产集成视为持续性事件:按计划轮换并迁移到服务账户,而不是等到下次有人离职时再处理。
7. 落实合规生命周期治理
审计人员检查的是政策和证据,而不是工具。先询问问题 4——涉及持卡人数据时,会直接触发 PCI-DSS。即便平台自身的风险状况并不构成要求,企业买家也会在采购过程中要求符合 SOC 2。
- SOC 2(CC7.2、C1.2):制定涵盖密钥完整生命周期的书面政策——配置、轮换、撤销、销毁——并提供政策实际执行的证据:密钥事件日志、定期访问审查、审批记录。Type II 要求这些控制措施在 3-12 个月的观察期内持续运行,因此,在审计前一周才通过的政策必然不合格;从第一天起就自动生成证据。
- PCI-DSS 4.0/4.0.1,要求 8.6.3(自 2025 年 4 月 1 日起强制执行):纠正一种误解——PCI 并未规定固定的轮换周期。它要求根据书面的针对性风险分析(要求 12.3.1)确定轮换频率,并且一旦怀疑或确认密钥泄露,无论是否到了计划时间,都必须立即轮换。此外,还需对 API 事务进行防篡改日志记录,保留 12 个月,且最新的 3 个月内的日志必须可立即访问。
- 合规压力正是成熟平台将这些能力作为产品功能而非政策的原因:强制过期、过期警告和强制轮换提醒;记录每次创建/使用/轮换/撤销操作及其执行者、时间和原因的审计日志;以及服务账户本身——每项功能都会生成审计人员要求的证据。
完整的逐框架对照表:references/compliance-lifecycle-matrix.md。
故障模式
反模式清单,依据 OWASP API2 编写——每项都可能直接导致审计问题:
- 将 API 密钥作为敏感操作的唯一凭证,或将密钥识别与用户身份验证混为一谈。
- 静态存储明文密钥,或使用没有 KMS 持有密钥的可逆加密。
- 缺少密钥时回退到硬编码默认值,而不是在启动时崩溃。
- 范围的默认值采用失败开放策略——创建时省略范围会授予完全访问权限。
- 未对密钥验证和密钥创建端点实施速率限制或暴力破解防护(应将它们视为登录端点)。
- 在身份验证路径上使用非恒定时间的哈希比较。
- 密钥没有所有者、范围说明或过期时间——这是不可见的基础设施。
- 上一个密钥在最后使用量遥测归零前就被删除(因轮换导致的中断),或创建新密钥时未安排撤销旧密钥(攻击面加倍)。
- 生产集成仍在使用离职员工的个人密钥运行。
- 将 Webhook 签名密钥按 API 密钥的方式管理,或反之。
衡量标准
门槛——反复迭代设计,直到每项都通过:
- 存储:100% 的存储密钥都经过哈希处理(不可恢复层级)或由 KMS 加密(可恢复层级);静态存储中不允许存在明文密钥,并通过架构审计验证,而非仅凭策略声明。
- 清单:每个有效密钥都标有所有者、范围,以及过期时间或有记录的豁免。
- 轮换:已编写并至少端到端演练过一次操作手册——真实密钥完成轮换且零停机,并确认旧密钥的流量归零后再将其删除。
- 自助服务:无需提交支持工单即可完成所有四项操作(注册、创建、轮换、撤销)。
从第一个月起建立基线并持续改善以下趋势(行业尚无统一阈值):从发现泄露到撤销所需的时间、最后使用时间超过 90 天的有效密钥占比、生产流量中服务账户密钥相对于个人密钥的占比。
调用示例
- “为我们的公共 API 设计 API 密钥系统——目前我们为每个账户签发一个 UUID,并以明文形式存储在 Postgres 中。”
- “定义一种密钥格式和前缀方案,让泄露的密钥能够被机密扫描器检测到。”
- “我们的企业客户在询问如何轮换 API 密钥——设计零停机轮换流程及相应的仪表板 UX。”
- “一名工程师刚刚离职,我们有一半集成使用的是他创建的密钥——修复所有权模型。”
参考资料
samber/developer-platform-skills@bulk-data-sharing-design——用于批量文件/数据湖交付的每位接收方存储凭据,其生命周期独立于本技能涵盖的 API 密钥。- references/vendor-key-format-census.md——七家供应商的前缀分类、GitHub 的熵计算、Secret Scanning Partner Program 的六个步骤,以及各供应商的范围限定机制和所有权模型。
- references/storage-and-lookup-schema.md——密钥表架构、基于前缀的查找流程、哈希决策细节及可恢复模式的存储方式。
- references/rotation-runbook.md——零停机轮换操作手册示例、Stripe/AWS/Azure 机制、宽限期周期表及离职交接流程。
- references/compliance-lifecycle-matrix.md——SOC 2 和 PCI-DSS 4.0 的要求,以及这些要求对应的密钥生命周期控制和产品功能。