OAuth2 Provider Design 是一套面向平台与 API 团队的决策指导,用于设计 B2B SaaS 向第三方应用提供的 OAuth2 授权服务器接口:包括协议配置、令牌生命周期、权限范围分类、同意页面、应用注册与验证。其目标是让被攻破的应用或泄露的令牌成为一个可控事件,并避免平台日后被迫进行大规模改造。
定位与目标配置
这不是 RFC 教程,而是面向平台/API 团队的决策指导。目标配置为 OAuth 2.1,并需始终注意一个细节:RFC 9700(BCP 240,OAuth 安全最佳当前实践)已于 2025 年 1 月定稿并获批;而整合后的 OAuth 2.1 文档(draft-ietf-oauth-v2-1)仍处于草案状态,在将其作为已发布标准引用前需核对其当前状态。无论该文档自身发布状态如何,相关要求已是既定共识。不得在未确认的情况下声称 OAuth 2.1 本身已是已发布的 RFC。
先澄清问题
设计前应先提问,每个答案都会改变后续步骤,建议批量提问。问题包括:全新建设还是存量改造(存量改造需了解当前运行的授权类型、是否有客户端依赖 implicit 或密码授权、是否开启刷新轮换、已注册应用数量);客户端类型(服务端机密应用、浏览器 SPA、原生/CLI 应用、AI 智能体或 MCP 宿主);应用是仅代表已登录用户行动,还是也拥有自身身份(机器人/应用令牌、组织级访问);数据敏感度上限(权限范围是否可触及他人数据、批量数据或受监管的金融/健康数据);谁批准安装(仅终端用户还是也包括组织管理员);构建基础与投入上限(从零构建授权服务器,还是基于已支持轮换/DPoP 配置的身份产品)。若运行环境有持久记忆,应保存核心决策,如授权类型清单、TTL 与轮换策略、权限命名约定与令牌类型绑定、验证层级与阈值。
谁同意:终端用户、组织管理员或两者
B2C/个人用户只有一个同意界面,即终端用户屏幕,同意文案质量与权限最小化承载全部信任决策。B2B/组织工作区有两个同意界面:终端用户同意,组织管理员可在其之前或之上限制安装(如 Slack 管理员批准应用、Microsoft 管理员同意,其中应用身份权限只能由管理员同意)。Slack 的开发者指南指出:请求超出必需的权限可能导致用户或管理员拒绝安装——过度授权是转化风险,且终端用户的「同意」无法替你通过这道关卡。协议核心、令牌生命周期与通俗同意文案规则对两者相同,差异仅在审批拓扑与应用身份/组织级权限层级。B2B 提供方必须把管理员界面(审批队列、组织级授权审查、应用身份权限层级)作为步骤 2-3 的一等部分来设计,而不是等第一个企业客户提出时再补。
工作流程
按序构建:协议核心 → 权限范围分类与同意页面 → 注册与验证程序 → 高级加固(仅在必要时)。
1. 协议核心
实现 authorization_code(PKCE S256,对所有客户端强制,公开与机密一视同仁)、client_credentials、refresh_token 和 device_authorization(RFC 8628,用于 CLI 与无头客户端)。不要实现 implicit 或密码授权——两者在 OAuth 2.1 中已移除。重定向 URI 精确字符串匹配,唯一标准例外是原生应用 localhost 重定向中的端口号。RFC 9700 的理由:模式匹配「实现更复杂、更易出错」,且「在生产环境中观察到多个利用模式匹配实现缺陷的成功攻击」。绝不在 URI 查询字符串中接受 bearer 令牌,只用 Authorization 头或 POST 体。授权码:单次使用,最长 10 分钟。访问令牌:默认约 1 小时(GitHub App 与 Google 约 1 小时,Microsoft Entra 60-90 分钟)。JWT 访问令牌尤其要短,因为 JWT 无法在有效期内像不透明数据库令牌那样被撤销。
刷新令牌姿态有三个候选,按安全价值排序:发送方约束(DPoP)> 轮换加重用检测 > 不轮换加每客户端上限;按第三方客户端库兼容性排序则相反;按投入排序 DPoP > 轮换 > 不轮换。默认档位是轮换加令牌族重用检测:每个刷新令牌都属于可追溯至原始授权的令牌族,已消费的令牌再次出现则撤销整个族。应从第一天起提供约 10-30 秒的重用宽限窗口,否则多标签 SPA 与网络重试会被误判为攻击。DPoP 是最强但生态支持近乎为零的选项(一项发行方调查中,18 家主流发行方无一在可用的发现文档中声明支持 DPoP),仅在令牌守护金融或健康数据,或长寿命 AI 智能体令牌扩大泄露影响面时提升使用(Bluesky 强制 DPoP 的部署证明其可大规模生产使用)。不轮换仅保留两种受限形式:机密客户端(客户端认证已实现发送方约束),以及 Google 的封顶式模型(每账户每客户端最多 100 个刷新令牌,最旧的静默失效,实现时需复核该数字)。公开客户端的无限可复用刷新令牌在 2.1 下被禁止。浏览器客户端的刷新令牌寿命应最短(Microsoft 对 SPA 设为 24 小时,其他场景为 90 天不活跃)。
2. 权限范围分类与同意页面
两个粒度档位:细粒度按资源权限与 resource:action 范围。默认档位是 resource:action 命名,带读写拆分与只读默认,这是 Slack、Microsoft Graph、Stripe Connect 的主流做法。细粒度按资源权限是稀缺选项(如 GitHub Apps 的 50 多个独立权限、按仓库限制、1 小时安装令牌),当组织管理员要求审批策略、有合规制度或范围触及组织级数据时启用。已删除的反模式是单一宽泛的万能范围。分类规则:只增不改,永不重新定义既有范围含义;若应用可同时持有应用身份与用户委托访问,则第一天就把每个范围绑定到令牌类型;在资源类型确实不同时接受范围数量膨胀。
同意页面:把每个范围逐条翻译为通俗句子,绝不分桶、绝不显示原始范围字符串;支持部分授予,并始终在服务端比对已授予与已请求的范围;支持增量授权,重新同意页面只显示净新增范围。没有严格的同意转化率研究,流传的流失百分比来自厂商博客而非实测,应以安全与 UX 理由论证同意设计。
3. 注册与验证程序
客户端注册:默认采用人工审核的开发者门户注册。没有任何主要 B2B SaaS 平台提供无门槛的公开动态客户端注册,GitHub、Slack、Stripe、Salesforce 都要求门户注册加审核。仅在刻意服务 MCP/AI 智能体生态(客户端需动态发现服务器)时,才提升为受控 DCR(RFC 7591 置于初始访问令牌之后、限速、所有元数据视为不可信输入)。开放无门槛 DCR 应删除:一项 2026 年 5 月的预印本探测 119 个支持 OAuth 的远程 MCP 服务器,发现其中 96.6% 存在 DCR 缺陷;MCP 规范本身在 2025-2026 年间将 DCR 从 SHOULD 降为 MAY 再到弃用。
验证层级,按每单位开发者摩擦换取的信任排序:第三方安全评估 > 自我声明 > 发布者身份验证。默认档位是每个上架应用都做发布者身份验证(如 Microsoft 的模型:域名加已验证合作伙伴账户,免费,准备就绪的发布者「几分钟内完成验证」)。它证明身份连续性而非质量,并配合 Microsoft 的实际执行杠杆:在风险管控租户中,未验证发布者无法获得超出基本资料的权限同意。自我声明是中间档,成本低(Microsoft 称「大多数声明可在一小时内完成」)且明确未经独立验证;三种信号在列表界面应视觉上可区分。强制第三方安全评估是稀缺档:数月日历时间,外加由开发者而非平台支付评估费。每个被研究的项目都划出一条明确触发线:一旦范围授予对他人数据或 PII(而非仅请求者自身)的访问,就提升到该档,并按 CASA 的 12 个月节奏每年复评。未验证应用应留有合法的测试通道,仿照 Google 的模式:有界具名测试用户、可见警告页面、硬性上限(Google 为 100 名用户终身上限)。
限制
资料未提供具体价格数值(仅提及 CASA 定价为社区报告、完整渗透测试档比扫描档高约一个数量级,具体数字在参考文件中);未提供完整端点与存储机制细节(在 references/protocol-baseline.md);未提供完整分类与同意机制原型(在 references/scope-taxonomy-archetypes.md、references/consent-screen-design.md);部分阈值(Google 刷新令牌数量、CASA 定价、OAuth 2.1 草案状态)需在实现时复核。