RFC 9700 — OAuth 2.0 安全最佳实践学习

简介: 本文详解OAuth 2.0安全演进与RFC 9700最佳实践,涵盖OAuth诞生背景、2.0框架确立、RFC 6819威胁模型到RFC 9700(2025年1月发布)的8年打磨历程,并系统梳理十大核心安全要求,如禁用密码模式、强制PKCE、精确重定向URI匹配等。

一、背景:为什么需要这份最佳实践?

OAuth 协议的诞生与演进

OAuth 的故事始于2006年11月。当时 Twitter 工程师 Blaine Cook 正在实现 Twitter 的 OpenID 集成,与社交书签网站 Ma.gnolia 的开发者 Chris Messina 讨论后,两人意识到业界缺少一种开放标准来实现 API 的委托授权——即"让第三方应用在不获取用户密码的前提下访问用户数据"。2007年4月,一个由 Google、Twitter 等公司的工程师组成的小型讨论组成立,着手起草 OAuth 协议。2007年10月,OAuth Core 1.0 最终草案发布。

2010年4月,OAuth 1.0 以 RFC 5849 的形式被 IETF 正式发布为信息性标准(Informational RFC)。然而 OAuth 1.0 的加密签名机制实现复杂、对移动端和浏览器应用不够友好,业界很快开始推动下一代协议的设计。

RFC 6749:OAuth 2.0 框架的确立

IETF 于2009年成立了 OAuth 工作组(OAuth WG),由 Dick Hardt 担任 OAuth 2.0 规范的编辑,着手设计全新的 OAuth 2.0 框架。2012年10月,RFC 6749(The OAuth 2.0 Authorization Framework)和 RFC 6750(Bearer Token Usage)正式发布,标志着 OAuth 2.0 成为行业标准。

OAuth 2.0 相比 1.0 做了根本性的简化——去掉了复杂的加密签名,改用 TLS 保护传输安全,并定义了多种授权模式(授权码、隐式、密码、客户端凭证)以适配不同的应用场景。这种灵活性使得 OAuth 2.0 被迅速广泛采纳,成为互联网身份授权的事实标准,被 Google、Facebook、Microsoft、GitHub 等几乎所有主流平台采用。

但灵活性也埋下了隐患。RFC 6749 将许多安全机制定义为"可选"(OPTIONAL),而非"强制"(MUST),给了开发者太多"不安全但合规"的选择空间。

从威胁模型到安全最佳实践:RFC 9700 的诞生

2013年1月,IETF 发布了 RFC 6819(OAuth 2.0 Threat Model and Security Considerations),由 Torsten Lodderstedt、Mark McGloin 和 Phil Hunt 起草,首次系统梳理了 OAuth 2.0 面临的安全威胁。然而,这份文档发布后的数年间,OAuth 的应用场景远远超出了最初的设想——从传统的 Web 应用扩展到移动 App、单页应用(SPA)、IoT 设备、微服务架构等,新的攻击面和攻击手法不断涌现,RFC 6819 的覆盖范围已经不够。

2016年11月,Torsten Lodderstedt(时任 YES Europe AG,OAuth WG 联合主席)提交了名为 draft-lodderstedt-oauth-security-topics 的个人草案,率先将近年来发现的新型攻击(如 Mix-Up Attack、授权码注入等)汇总为一份更新的安全指引。2017年3月,该草案被 OAuth 工作组正式采纳为工作组文档(draft-ietf-oauth-security-topics-00),初始作者为三人——Torsten Lodderstedt、John Bradley(时任 Ping Identity)和 Andrey Labunets(时任 Facebook 安全工程师)。Daniel Fett(此前参与了 CCS 2016 的 OAuth 形式化安全分析)在后续版本中加入,成为第四位作者。在最终发布的 RFC 9700 中,四位作者的隶属分别为 SPRIND、Yubico、独立安全研究员、Authlete。

此后,这份草案经历了长达 8 年、30 个版本(v00 至 v29)的持续修订,每一轮修订都在消化新发现的攻击和来自行业的反馈:

  • 2017-2018年(v00-v10):建立初始框架,纳入隐式流风险、PKCE 推荐、重定向 URI 验证要求等核心议题。从工作组采纳之初,文档即被定位为 "Best Current Practice"(BCP)级别,意味着它将成为具有约束力的行业最佳实践,而非仅仅是参考性文档。
  • 2019-2021年(v12-v18):大幅扩展攻击模型,纳入发送者约束令牌(DPoP/mTLS)、刷新令牌轮换、混合攻击防御(推动 RFC 9207 的配套制定)等内容。
  • 2022-2023年(v20-v24):进入成熟期,细化各项要求的措辞,平衡安全性与向后兼容性。2023年11月提交 IESG 审批。
  • 2024年(v25-v29):通过 IETF Last Call、IESG 评审和投票,完成最终修订。2024年6月获批进入 RFC 编辑队列。
  • 2025年1月30日:正式发布为 RFC 9700(BCP 240)。

RFC 9700 明确更新了 RFC 6749(OAuth 2.0 核心框架)、RFC 6750(Bearer Token)和 RFC 6819(OAuth 2.0 威胁模型),成为 OAuth 2.0 安全指引的最新权威文档。

RFC 9700 与 OAuth 2.1 的关系

值得一提的是,OAuth 社区同时在推进另一份重要文档——OAuth 2.1(draft-ietf-oauth-v2-1),由 Aaron Parecki、Dick Hardt 和 Torsten Lodderstedt 联合起草,首个草案于2020年3月发布。OAuth 2.1 的目标是将 RFC 9700 的安全要求直接"内化"到 OAuth 核心协议中,形成一份取代 RFC 6749 的新版规范。换句话说,RFC 9700 是"给现有 OAuth 2.0 打安全补丁",而 OAuth 2.1 则是"把补丁合进主线版本"。在 OAuth 2.1 正式发布之前,RFC 9700 是指导 OAuth 2.0 安全实施的最权威文档。

前置知识:OAuth 2.0 的核心角色与交互模型

在进入具体的安全实践之前,需要先理解 OAuth 2.0 中的四个核心角色以及它们之间的交互关系。后文每条最佳实践都会标注它影响的是哪些角色之间的交互,帮助你判断"这件事该谁来做"。

四个核心角色

  • 资源所有者(Resource Owner) —— 通常就是终端用户。拥有受保护数据的人,比如一个 GitHub 用户拥有自己的代码仓库。
  • 客户端(Client) —— 想要访问用户数据的第三方应用。比如一个项目管理工具想读取用户的 GitHub 仓库列表。客户端分两类:公开客户端(如浏览器 SPA、移动 App,无法安全保存密钥)和机密客户端(如有后端服务器的 Web 应用,可以安全保存密钥)。
  • 授权服务器(Authorization Server, AS) —— 验证用户身份、征得用户同意、颁发令牌的服务。比如 GitHub 的 OAuth 登录服务。它是整个安全架构的信任中枢。
  • 资源服务器(Resource Server, RS) —— 托管受保护资源、接受令牌并返回数据的 API 服务。比如 GitHub 的 REST API。

标准授权码流程中的交互

RFC 9700 的安全最佳实践,就是针对上述每一步交互中可能被攻击的环节,给出具体的防护要求。后续第二章中,每条实践都会标注它保护的是哪几步交互、责任方是哪个角色,帮助团队明确"这个安全措施应该由谁来实施"。

二、十大核心安全最佳实践

以下按 RFC 2119 关键词的严格程度排序:MUST NOT(禁止)> MUST(必须)> SHOULD NOT(不应)> SHOULD(应当),优先展示约束力最强的要求。每条实践标注了它影响的组件交互和责任方,方便团队分工落地。

▸ 禁止级(MUST NOT)

1. 禁用资源所有者密码凭证模式

要求级别:MUST NOT(禁止使用)

涉及交互用户客户端授权服务器 | 责任方:授权服务器(不再支持该授权类型)、客户端(不再使用该流程)

在这种模式下,用户需要把用户名和密码直接交给第三方客户端,由客户端代替用户向授权服务器提交凭证。这违背了 OAuth 的核心设计哲学——用户不应该把密码告诉任何第三方。RFC 9700 将其定为最高级别的禁令(MUST NOT),因为它从根本上破坏了 OAuth 的安全模型。

为什么是"禁止"而不仅仅是"不推荐":密码模式绕过了授权服务器的登录页面,意味着多因素认证(MFA)、条件访问策略、联合身份(SSO)等现代安全机制全部失效。同时,它让客户端直接持有用户密码,一旦客户端被攻破,泄露的是密码本身(通常跨平台复用)而不仅仅是令牌(可撤销、有时效)。

OWASP 对应指引:OWASP 明确声明此授权类型"不应使用"。它直接违反了 OWASP 的最小权限原则和凭证保护原则。OWASP API Security Top 10 中的 API2:认证失效(Broken Authentication) 同样覆盖了凭证暴露问题。

真实案例

  • Microsoft 明确弃用密码模式:Microsoft 在其身份平台文档中明确警告"Microsoft 建议你不要使用 ROPC 流",原因包括:该流程要求应用直接处理用户密码,增大了攻击面;它无法与多因素认证(MFA)、条件访问策略、联合身份(SSO)等现代安全机制兼容;它本质上是"冒充"而非"授权"——用户无法控制第三方应用获得了哪些权限。这代表了行业头部厂商的一致判断。
  • 密码模式助长钓鱼攻击:密码模式训练用户"把密码交给第三方应用是正常的",这与安全教育中"永远不要在非官方页面输入密码"的原则完全矛盾。安全研究机构 AppOmni 在 2025 年的报告中指出,OAuth 钓鱼攻击(攻击者伪装成合法应用诱骗用户授权)已成为绕过密码和 MFA 的主要手段。密码模式的存在为这类社会工程学攻击提供了"合理性外衣"——用户已经习惯了在第三方界面输入密码。
  • 核心对比:授权码模式下,用户的密码只在授权服务器的官方页面输入,第三方客户端从未接触过密码。即使客户端被攻破,泄露的是令牌(可被撤销、有时效)而非密码(通常跨平台复用且难以全部更换)。

▸ 强制级(MUST)

2. 强制使用 PKCE(Proof Key for Code Exchange)

要求级别:MUST(公开客户端和授权服务器)/ SHOULD(机密客户端)

涉及交互客户端授权服务器(流程步骤 ②⑤⑥)| 责任方:客户端(生成 code_verifier 和 code_challenge)、授权服务器(验证 PKCE 参数并防止降级)

PKCE 解决的是授权码在传输过程中被截获后滥用的问题。它的原理类似于"信封加锁":客户端在请求授权码时先发送一个"锁"(code_challenge),授权码返回后,客户端用对应的"钥匙"(code_verifier)来换取令牌。即使攻击者截获了授权码,没有"钥匙"也无法使用。

对于公开客户端(SPA、移动 App)这是硬性要求,因为它们无法安全存储 client_secret,PKCE 成为唯一能绑定授权码与客户端会话的机制。授权服务器不仅必须支持 PKCE,还必须防止攻击者剥离 PKCE 参数的"降级攻击"。

OWASP 对应指引:OWASP OAuth2 Cheat Sheet 将 PKCE 列为防御授权码拦截攻击(Authorization Code Interception Attack)的核心手段。OWASP 强调 code_challenge_method 应使用 S256(SHA-256哈希),不应使用 plain 方式。

真实案例

  • 移动端自定义 URI Scheme 劫持:Doyensec 在 2025 年的安全报告中详细描述了"Redirect Scheme Hijacking"攻击。在 Android 和 iOS 上,恶意应用可以注册与目标应用相同的自定义 URI scheme(如 com.example.app://callback),从而截获授权码。如果没有 PKCE 保护,被截获的授权码可以直接用来获取令牌。Android 的 Verifiable Links 和 iOS 的 Associated Domains 可以缓解此问题,但 PKCE 是最根本的防线。
  • PKCE 降级攻击与 GHSA-qgp8-v765-qxx9:2025 年 4 月,Cloudflare 的 @cloudflare/workers-oauth-provider 库被发现存在 PKCE 降级漏洞(GHSA-qgp8-v765-qxx9,CVSS 5.3):该库在 0.0.5 版本之前未正确强制执行 PKCE 校验,攻击者可以跳过 code_verifier 检查,直接使用截获的授权码获取令牌。此案例说明即便 PKCE 已是行业共识,授权服务器实现层面的疏忽仍然会导致保护失效。

3. 精确匹配重定向 URI

要求级别:MUST(精确字符串匹配)

涉及交互授权服务器 验证 客户端 注册的 redirect_uri(流程步骤 ②④)| 责任方:授权服务器(执行精确匹配校验)、客户端(不暴露开放重定向端点)

重定向 URI 是授权码"被送回"客户端的地址。如果授权服务器的验证不严格——比如只检查域名不检查路径,或者允许通配符——攻击者就可以构造一个特殊的 URI,让授权码被发送到攻击者控制的地址。这是 OAuth 实现中最常见也最危险的漏洞类别之一。

授权服务器必须完整比较协议(scheme)、主机名(hostname)、端口(port)和路径(path),禁止模式匹配或前缀匹配。客户端则不能暴露任何可将请求转发到任意地址的开放重定向端点,否则攻击者可以利用合法的 redirect_uri 作为跳板。

OWASP 对应指引:OWASP Top 10 中的 A01:访问控制失效(Broken Access Control) 下的开放重定向(Open Redirect)问题直接关联此项。

真实CVE案例

  • CVE-2023-6927(Keycloak 开放重定向漏洞):Red Hat Keycloak(广泛使用的开源身份认证服务器,即授权服务器角色)在 redirect_uri 验证中存在缺陷,攻击者可以绕过校验规则,将用户重定向到恶意网站,从而窃取授权码或令牌。此漏洞影响了修复前的多个 Keycloak 版本。
  • CVE-2024-8883(Keycloak 另一个重定向URI验证漏洞):同样是 Keycloak 中的重定向 URI 验证不严格导致的开放重定向,攻击者可借此窃取 OAuth 授权码。
  • CVE-2024-55017(Corezoid 平台账户接管):Corezoid 平台的 OAuth2 实现中,redirect_uri 参数验证不充分,攻击者利用开放重定向将授权码截获,实现完整的账户接管(Account Takeover)。
  • **NDSS 2025 研究论文** "Do (Not) Follow the White Rabbit: Challenging the Myth of Harmless Open Redirection" 指出,开放重定向在 OAuth 场景下远非"低危"漏洞,它可以直接升级为账户接管。

4. 防御跨站请求伪造(CSRF)

要求级别:MUST

涉及交互用户浏览器客户端(流程步骤 ④,授权码回调阶段)| 责任方:客户端(生成并验证 state 或使用 PKCE)

CSRF 攻击发生在授权码回调阶段——攻击者诱骗已登录的用户点击一个精心构造的回调链接,利用用户在授权服务器上的已有会话,让用户"不知不觉"地完成一次授权操作。推荐的防御方式是使用 PKCE(首选,因为同时防御了授权码注入)或加密绑定的 state 参数。

OWASP 对应指引:OWASP 的 CSRF Prevention Cheat Sheet 与 OAuth2 Cheat Sheet 均要求实施 state 参数或 PKCE 来绑定授权请求与用户会话。OWASP Top 10 曾长期将 CSRF 列为独立风险项(目前归入 A01:访问控制失效)。

真实案例

  • OAuth CSRF 账户关联攻击Doyensec 的报告中描述了一个完整的攻击链——攻击者用自己的账户启动一个 OAuth 授权流程(如"使用 GitHub 登录"),获取自己的授权码后中断流程,不完成回调。然后攻击者将包含该授权码的回调 URL 伪装成普通链接发送给受害者。如果客户端不验证 state 参数,受害者的浏览器会自动完成授权流程,将受害者的主站账户与攻击者的 GitHub 账户关联。此后攻击者可以直接用自己的 GitHub 账户登录受害者的主站账户。
  • GitHub OAuth App 授权钓鱼(2025 年):2025 年 3 月,安全社区披露了一起大规模 GitHub OAuth 钓鱼攻击——攻击者向约 12,000 个 GitHub 仓库批量创建伪装为"安全警告"的 Issue,诱骗开发者点击链接并授权一个恶意 OAuth 应用。由于 OAuth 授权流程发生在 GitHub(授权服务器)的官方页面上,用户很难分辨合法请求和恶意请求。一旦用户点击"Authorize",攻击者就获得了对用户代码仓库的持久访问权限。

5. 防御混合攻击(Mix-Up Attack)

要求级别:MUST(当客户端对接多个授权服务器时)

涉及交互客户端多个授权服务器(流程步骤 ②④⑤)| 责任方:授权服务器(在响应中返回 iss 参数)、客户端(校验 iss 参数匹配预期)

当一个客户端同时支持"用Google登录"和"用GitHub登录"时,会面临一种特殊威胁:恶意的授权服务器(或中间人)可以欺骗客户端,让客户端把从 Google 获取的授权码错误地发送给 GitHub 的令牌端点,从而泄露授权码。防御方式是授权服务器在授权响应中返回 iss(颁发者)参数(参见 RFC 9207),客户端验证该参数与预期的授权服务器一致。

OWASP 对应指引:OWASP 在身份验证相关指引中要求验证令牌的颁发者(issuer),确保令牌来源与预期一致。这与 OWASP Top 10 的 A07:身份识别和身份验证失效 直接关联。

真实案例

  • Fett, Küsters & Schmitz 首次形式化验证发现 Mix-Up AttackCCS 2016):德国特里尔大学的三位研究者在对 OAuth 2.0 进行首次全面的形式化安全验证时,意外发现了 Mix-Up Attack。该论文(被广泛引用)表明,当客户端注册了多个授权服务器时,攻击者可以利用恶意的授权服务器欺骗客户端,让客户端把授权码或令牌发送给错误的端点。这一发现直接推动了 RFC 9207(Authorization Server Issuer Identification)的制定,并最终写入 RFC 9700 成为强制要求。
  • 实际影响范围:任何支持"多种第三方登录"的应用(如同时支持 Google、GitHub、微信登录),如果客户端没有在回调中验证 iss 参数以确认授权响应来自预期的授权服务器,就可能受到这种攻击。

6. 公开客户端的刷新令牌必须使用发送者约束或轮换

要求级别:MUST(公开客户端的刷新令牌)/ SHOULD(访问令牌的发送者约束)

涉及交互客户端授权服务器(刷新令牌交换,步骤 ⑤⑥)、客户端资源服务器(携带令牌访问 API,步骤 ⑦⑧)| 责任方:授权服务器(实施轮换和重放检测)、客户端(支持 DPoP 或 mTLS)、资源服务器(验证发送者约束)

普通的 Bearer Token 就像"谁拿着就能用"的现金。发送者约束则像"记名支票"——即使被偷了,小偷也用不了,因为使用时需要证明自己就是支票上登记的人。mTLS 通过客户端证书、DPoP 通过加密证明来实现这种"记名"效果。

对于公开客户端(无法保存密钥的 SPA、移动 App),刷新令牌是高价值目标——它的有效期比访问令牌长得多,一旦被盗,攻击者可以长期获取新的访问令牌。因此 RFC 9700 对公开客户端的刷新令牌提出硬性要求:要么使用发送者约束,要么使用刷新令牌轮换(每次使用后换新)。轮换模式下,授权服务器如果检测到旧的刷新令牌被重复使用,应当撤销整个令牌家族。

OWASP 对应指引:OWASP 推荐使用 "Proof of Possession (PoP) tokens"(如 DPoP 或 mTLS)来提升安全性,并要求刷新令牌必须"sender-constrained 或使用 rotation"。这对应 OWASP Top 10 的 A07:身份识别和身份验证失效

真实案例

  • Storm-2372:俄罗斯关联黑客的 OAuth 令牌窃取行动(2024-2025年):Microsoft 于 2025 年 2 月披露,俄罗斯关联的威胁组织 Storm-2372 自 2024 年 8 月起利用 OAuth 设备码流程(Device Code Flow)进行大规模钓鱼攻击。攻击者向目标用户发送伪装为 Microsoft Teams 会议邀请的消息,诱骗用户在合法的 Microsoft 登录页面(授权服务器)上输入设备码。用户完成认证后,攻击者获取了用户的 access token 和 refresh token。由于这些令牌没有发送者约束,攻击者可以在自己的设备上长期使用,绕过密码和 MFA,持续访问受害者在资源服务器上的邮件、文件和其他 Microsoft 365 数据。该行动波及全球多个行业,包括政府、国防、电信和能源部门。
  • 刷新令牌重放检测的重要性:如果授权服务器实现了令牌轮换但没有做重放检测,攻击者可以在受害者之前使用被窃取的刷新令牌,获取新令牌对,然后合法用户的旧令牌失效——但攻击者已经拿到了新令牌。只有授权服务器检测到"同一个刷新令牌被使用两次"并撤销整个令牌家族,才能有效阻断这种攻击。

7. 防御授权码注入攻击

要求级别:MUST(通过 PKCE 或 OpenID Connect nonce)

涉及交互客户端授权服务器(流程步骤 ④⑤)| 责任方:客户端(发送 PKCE 或 nonce)、授权服务器(验证绑定关系)

授权码注入是指攻击者通过某种方式获取了合法用户的授权码(比如通过不安全的重定向),然后把这个授权码塞进自己的 OAuth 流程中提交给授权服务器。如果没有 PKCE 保护,授权服务器无法区分"是原来那个客户端在兑换码"还是"攻击者在冒用"。有了 PKCE,每个授权请求都有唯一的 code_verifier 与授权码绑定,攻击者没有原始的 verifier,就无法完成令牌交换。OpenID Connect 的 nonce 参数也能起到类似的绑定作用。

OWASP 对应指引:OWASP OAuth2 Cheat Sheet 将 PKCE 定位为防御授权码拦截和注入攻击的首要方案。这对应 OWASP Top 10 的 A07:身份识别和身份验证失效

真实案例

  • **USENIX Security 2025 论文**:Kaixuan Luo 等研究者对多个主流集成平台(Integration Platforms,如自动化工作流工具)进行了首次深入安全分析,发现普遍存在跨应用 OAuth 攻击漏洞。攻击者可以在平台 A 上通过恶意应用截获用户的授权码,然后将该授权码注入到平台 B 的 OAuth 流程中使用,获取受害者在平台 B 上的资源访问权。根本原因就是这些平台的客户端缺少 PKCE 等授权码与客户端会话的绑定机制,授权码变成了可以"转让"的凭证。
  • 可变声明攻击(Mutable Claims Attack)Doyensec 的报告描述了一种与授权码注入同源但攻击路径不同的账户接管手法。许多客户端使用授权服务器返回的 email 字段来识别和匹配用户,但 email 是用户可自行修改的可变字段。攻击者在自己组织的身份服务(如 Azure AD)中创建一个与目标用户相同 email 的账户,然后通过"用企业账户登录"的 OAuth 流程登录目标应用,客户端根据 email 匹配将攻击者的会话关联到目标用户的账户上,完成接管。正确的做法是客户端使用不可变的唯一标识符(如 sub 字段)来关联用户身份。更多讨论见第三章"使用不可变标识符进行用户身份关联"。

▸ 不应级(SHOULD NOT)

8. 禁用隐式授权模式(Implicit Grant)

要求级别:SHOULD NOT(不应再使用)

涉及交互授权服务器用户浏览器客户端(令牌直接通过浏览器传递)| 责任方:授权服务器(不再支持 response_type=token)、客户端(迁移到授权码模式)

隐式模式把访问令牌直接放在浏览器 URL 的片段(fragment)中返回给客户端,完全跳过了后端通道的令牌交换步骤(步骤 ⑤⑥)。这意味着令牌会出现在浏览器历史记录中,可能通过 HTTP Referer 头泄露给第三方网站,也容易被恶意浏览器插件截获。更关键的是,资源服务器收到令牌后无法验证它是否确实由该客户端合法获取——任何人拿到令牌都能直接使用。

虽然 RFC 9700 对此使用的是 SHOULD NOT 而非 MUST NOT(考虑到部分老旧系统的兼容性),但在实践中,业界已将隐式模式视为"弃用"。所有主流平台和安全指引都推荐客户端迁移到授权码模式 + PKCE。

OWASP 对应指引:OWASP OAuth2 Cheat Sheet 明确指出隐式授权已弃用(deprecated),要求客户端使用 response_type=code。OWASP Top 10 2021 中的 A07:身份识别和身份验证失效 也覆盖了此类令牌泄露场景。

真实案例

  • Facebook 令牌泄露事件(2018 年):Facebook 的"View As"功能中存在多个代码 Bug,导致视频上传器在该模式下错误生成了访问令牌。Facebook 最终确认约 3000 万用户的令牌被窃取(初始估计为 5000 万)。虽然这是 Facebook 自身的代码缺陷而非 OAuth 隐式流协议本身的漏洞,但它深刻说明了令牌在客户端暴露的危险性——一旦令牌以不安全方式传递或生成,就可能被大规模窃取。隐式流把令牌直接暴露在 URL 中的设计,同样面临这种系统性风险。
  • 常见攻击路径:在使用隐式流的应用中,攻击者通过在页面中嵌入第三方图片或链接,利用 Referer 头窃取 URL 中的令牌。Doyensec 在 2025 年的报告中指出,这种"Client Confusion Attack"在隐式流中尤其普遍——攻击者将为其他客户端颁发的 Token 注入到目标客户端中,如果目标客户端不验证 Token 的 client_id,就会被劫持。

▸ 推荐级(SHOULD)

9. 访问令牌应限制受众和权限范围

要求级别:SHOULD(应当)

涉及交互授权服务器(颁发受众受限的令牌)→ 资源服务器(验证令牌受众)| 责任方:授权服务器(在令牌中标注目标资源服务器)、资源服务器(拒绝不属于自己的令牌)

如果一个令牌可以在任意资源服务器上使用,那么当其中一个资源服务器被攻击时,攻击者就能拿着泄露的令牌去访问用户在其他所有资源服务器上的数据。限制受众就像给每把钥匙标注"只能开A号门",即使钥匙丢了,也只影响A号门后面的东西。权限范围(scope)则应遵循最小权限原则——客户端请求的权限不应超过它实际需要的范围。

OWASP 对应指引:OWASP 要求 "Bearer tokens 必须限制在单一受众范围内",资源服务器对每个请求都应验证令牌的受众(audience)和权限范围(scope)。这对应 OWASP Top 10 的 A01:访问控制失效A04:不安全的设计

真实案例

  • Scope Upgrade Attack(权限提升攻击)PortSwigger Web Security Academy 记录了一种攻击场景:如果授权服务器在令牌交换阶段接受 scope 参数并且不验证它是否与授权阶段一致,恶意客户端可以在令牌请求中偷偷加入额外的权限范围,获取超出用户授权范围的数据访问权。例如,用户只授权了"读取个人资料",但恶意客户端在令牌请求中追加了"读取邮件"的权限——如果授权服务器不做一致性校验,就会颁发超出用户意愿的令牌。
  • CVE-2025-27371(JWT audience 歧义漏洞):OpenID Foundation 于 2025 年 2 月披露,IETF OAuth2 中基于 JWT 的客户端认证断言(RFC 7521/7523)在 audience 值的使用上存在规范歧义。不同的授权服务器对 JWT 中 audience 字段的解读方式不一致,导致攻击者可以构造一个 JWT 令牌,让它被本不应接受该令牌的资源服务器所接受。这正是令牌受众限制不严格带来的风险——同一令牌在不同服务间"串门"使用。

10. 客户端认证应使用非对称加密方法

要求级别:SHOULD(应当)

涉及交互客户端授权服务器(流程步骤 ⑤,令牌交换时的客户端身份验证)| 责任方:客户端(使用私钥签名)、授权服务器(验证签名并强制客户端认证)

客户端认证就是"客户端向授权服务器证明自己的身份"。传统的方式是给客户端一个 client_secret(对称密钥),但这个密钥需要在客户端和授权服务器之间共享,一旦从客户端侧泄露就会被冒用。非对称加密方式(如 mTLS 或 private_key_jwt)则是客户端持有私钥、授权服务器持有公钥,客户端用私钥签名来证明身份,私钥永远不需要离开客户端,大幅降低了泄露风险。

OWASP 对应指引:OWASP 明确推荐"使用非对称方法进行客户端认证,如 mTLS 或 private_key_jwt",避免存储对称密钥。这对应 OWASP Top 10 的 A02:加密失败(Cryptographic Failures)A07:身份识别和身份验证失效

真实案例

  • GitHub 密钥泄露报告:GitHub 于 2025 年 4 月发布的报告显示,其 Secret Scanning 功能在 2024 年全年检测到超过 3900 万个暴露的密钥,其中包括各类 API 密钥和 OAuth 凭证。这些泄露的密钥可被用于冒充合法客户端向授权服务器申请令牌。使用非对称加密认证方式可以从根本上消除此类风险——即使公钥被公开,没有私钥也无法完成认证。
  • CVE-2025-31123(Zitadel JWT密钥过期校验缺失):开源身份平台 Zitadel(作为授权服务器)在使用 JWT 进行客户端认证时,未检查密钥是否已过期,导致攻击者可以使用已过期的密钥材料进行认证。这提醒我们即使采用了非对称认证,授权服务器的实现细节也至关重要。

三、其他重要安全要求

以下要求同样来自 RFC 9700,虽未列入十大核心实践,但对安全实施同样关键。每条标注了涉及的组件和流程步骤。

通信安全

涉及交互:所有组件之间的通信(步骤①-⑧全链路)| 责任方:所有组件(客户端、授权服务器、资源服务器)

RFC 9700 要求所有 OAuth 通信必须使用 TLS(HTTPS)。除了 localhost 回环地址用于原生应用开发外,禁止使用 HTTP 方案的重定向 URI。这是防止中间人攻击的基础防线。

令牌存储安全

涉及交互客户端 本地存储(步骤⑥⑦之间)| 责任方:客户端

访问令牌和刷新令牌不应存储在浏览器的 localStorage 或 sessionStorage 中(容易被 XSS 攻击窃取),不应在 URL 参数中传递令牌,也不应在服务器日志中记录令牌。

授权码的一次性使用

涉及交互客户端授权服务器(步骤⑤)| 责任方:授权服务器(检测并拒绝重复使用)

授权码只能使用一次。如果授权服务器检测到同一授权码被多次使用,应当撤销基于该授权码已颁发的所有令牌。

避免在URL中暴露敏感信息

涉及交互客户端授权服务器(步骤②)| 责任方:客户端(使用 PAR)、授权服务器(支持 PAR 端点)

RFC 9700 要求敏感信息不应通过 URL 参数传递。对于需要传递敏感参数的场景,推荐使用 PAR(Pushed Authorization Requests,RFC 9126) 将授权参数通过后端通道传递。

使用不可变标识符进行用户身份关联

涉及交互授权服务器客户端(步骤⑥,返回用户信息时)| 责任方:客户端(使用 sub 字段关联用户)、授权服务器(提供稳定的 sub 标识)

在使用 OAuth 实现"第三方登录"时,应用应使用授权服务器返回的不可变唯一标识符(如 OpenID Connect 中的 sub 字段)来关联用户,而非 email、用户名等可变字段。使用可变字段会导致"可变声明攻击"——攻击者通过修改自己账户的可变属性来匹配目标用户,从而实现账户接管(详见第二章第 7 节案例)。

四、速查对照表

排序与第二章一致,按 RFC 2119 严格程度从高到低排列。表中 AS = 授权服务器,RS = 资源服务器。

#

安全最佳实践

要求级别

涉及组件 / 责任方

OWASP 对应项

代表性 CVE / 事件

禁止级 MUST NOT

1

禁用密码模式

MUST NOT

用户客户端AS · 责任方:AS + 客户端

API Security API2

Microsoft 弃用 ROPC / OAuth 钓鱼攻击链

强制级 MUST

2

强制 PKCE

MUST / SHOULD(机密客户端)

客户端AS(步骤②⑤⑥)· 责任方:客户端 + AS

OAuth2 Cheat Sheet

移动端 scheme 劫持 / GHSA-qgp8-v765-qxx9

3

精确匹配 redirect_uri

MUST

AS 验证 客户端(步骤②④)· 责任方:AS + 客户端

A01 开放重定向

CVE-2023-6927 / CVE-2024-8883 / CVE-2024-55017

4

CSRF 防护

MUST

用户浏览器客户端(步骤④)· 责任方:客户端

CSRF Prevention / A01

OAuth CSRF 账户关联 / GitHub OAuth 钓鱼(2025)

5

混合攻击防御

MUST

客户端多个 AS(步骤②④⑤)· 责任方:AS + 客户端

A07 身份验证失效

CCS 2016 论文 → RFC 9207

6

刷新令牌发送者约束 / 轮换

MUST(公开客户端)

客户端AS(步骤⑤⑥)、客户端RS(步骤⑦⑧)· 责任方:AS + 客户端 + RS

A07 身份验证失效

Storm-2372 OAuth 设备码钓鱼

7

授权码注入防御

MUST

客户端AS(步骤④⑤)· 责任方:客户端 + AS

OAuth2 Cheat Sheet / A07

USENIX 2025 跨平台攻击

不应级 SHOULD NOT

8

禁用隐式授权

SHOULD NOT

AS浏览器客户端(跳过步骤⑤⑥)· 责任方:AS + 客户端

OAuth2 Cheat Sheet / A07

Client Confusion Attack / Referer 头令牌泄露

推荐级 SHOULD

9

令牌受众限制

SHOULD

AS(颁发)→ RS(验证)· 责任方:AS + RS

A01 / A04

Scope Upgrade Attack / CVE-2025-27371

10

非对称客户端认证

SHOULD

客户端AS(步骤⑤)· 责任方:客户端 + AS

A02 / A07

CVE-2025-31123 / GitHub 3900万密钥泄露报告

五、术语速查表

缩写/术语

全称

简要说明

OAuth 2.0

Open Authorization 2.0

开放授权协议,允许第三方应用在用户授权下访问资源

PKCE

Proof Key for Code Exchange

授权码交换的证明密钥,防止授权码被截获后滥用

mTLS

Mutual Transport Layer Security

双向TLS认证,客户端和服务器双方互相验证身份

DPoP

Demonstration of Proof-of-Possession

持有证明机制,证明令牌使用者拥有对应的私钥

PAR

Pushed Authorization Requests

推送授权请求,通过后端通道传递授权参数

SPA

Single Page Application

单页应用,在浏览器中运行的前端应用

CSRF

Cross-Site Request Forgery

跨站请求伪造,诱骗用户执行非预期的操作

XSS

Cross-Site Scripting

跨站脚本攻击,在页面中注入恶意脚本

MFA

Multi-Factor Authentication

多因素认证,除密码外还需第二种验证方式

JWT

JSON Web Token

一种紧凑的、自包含的令牌格式

Bearer Token

持有者令牌,谁持有就能使用,无需额外身份证明

Refresh Token

刷新令牌,用于在访问令牌过期后获取新的访问令牌

Scope

权限范围,定义客户端可以访问的资源边界

Redirect URI

重定向地址,授权完成后将用户引导回的地址

Issuer (iss)

颁发者,标识令牌或授权响应由哪个授权服务器颁发

sub

Subject Identifier

主体标识符,授权服务器为用户分配的不可变唯一ID

audience (aud)

受众,标识令牌的预期使用者(即哪个资源服务器可以接受此令牌)

六、参考资料

目录
相关文章
|
13天前
|
人工智能 弹性计算 安全
AI真能成打工仔?阿里云OpenClaw虾友会现场“训虾”,百人脑暴!
北京时间3月13日晚7点,当北京的打工人还在晚高峰里“摸鱼”时,阿里巴巴朝阳科技园C区已经炸开了锅。百余位开发者、技术极客和“虾爸虾妈”齐聚一堂,把这里变成了OpenClaw虾友开放麦北京站的现场。没有枯燥的PPT轰炸,也没有高高在上的技术布道,就是一个真正的开放麦,大家聚在一起,就是要打破对AI的滤镜——不聊虚的,只看AI Agent怎么真刀真枪地干活。
|
15小时前
|
人工智能 Linux API
3分钟搞定OpenClaw(龙虾AI)联网!Tavily一键配置教程+全平台部署攻略+免费模型API配置详解
好不容易把OpenClaw(龙虾AI)部署完,结果一问最新信息就答非所问,要么直接说“无法访问网络”。没联网的OpenClaw只是个会背旧知识的聊天机器人,**只有联上网,它才真正成为能干活、能查资料、能实时处理信息的智能体**。
76 11
|
24天前
|
人工智能 安全 前端开发
阿里开源 Team 版 OpenClaw,5分钟完成本地安装
HiClaw 是 OpenClaw 的升级版,通过引入 Manager Agent 架构和分布式设计,解决了 OpenClaw 在安全性、多任务协作、移动端体验、记忆管理等方面的核心痛点。
1708 60
阿里开源 Team 版 OpenClaw,5分钟完成本地安装
|
9天前
|
SQL 前端开发 Java
【分层架构】Spring MVC三层架构 / DDD领域驱动四层架构 / 微服务分布式架构(DAO/Mapper/Repository/Service/Controller/Manager)
本文系统解析Java企业级分层架构(Controller/Service/Manager/Repository/DAO/Mapper),阐明各层职责边界、设计原则与典型误区,强调单一职责、依赖倒置、关注点分离等核心思想,助力构建高内聚、低耦合、易维护的可扩展系统。
359 11
|
9天前
|
人工智能 Linux API
三句话完成公众号发文|OpenClaw 阿里云/本地部署与百炼大模型配置实战指南
OpenClaw(曾用名Clawdbot、Moltbot)是一款面向个人与轻量团队的AI自动化代理工具,可通过自然语言指令完成内容创作、图文生成、格式转换、平台发布等流程化工作。对于自媒体运营、技术博主、职场用户而言,它能将原本数小时的内容产出与发布流程压缩到十几分钟,大幅降低重复操作成本。
205 4
|
21天前
|
弹性计算 运维 监控
阿里云2核2G配置38元和99元特价云服务器测评:实例性能、适用场景解析
2026年阿里云推出特价云服务器,其中38元/年轻量应用服务器和99元/年云服务器ECS经济型e实例受大量个人开发者、初创企业及学生关注。38元轻量服务器部署简易、运维简化、带宽弹性大,适合个人博客、小微应用测试等场景;99元ECS经济型e实例性能基础、长期成本稳定,适合小型企业官网、开发测试等场景。此外,还有199元/年的通用算力型u1实例可供选择。用户应理性评估自身业务需求,做出明智选择。
|
21天前
|
安全 Java API
Java 冷门但实用的技巧:让你的代码优雅十倍
Java 冷门但实用的技巧:让你的代码优雅十倍
114 26
|
12天前
|
机器学习/深度学习 算法 网络协议
AI算力狂飙背后的秘密:当“稳重老哥”Gloo遇上“极速引擎”NCCL
本文深度解析AI大模型训练中两大核心通信后端——Gloo与NCCL:前者是跨平台、高兼容的“稳健使者”,适配CPU及普通网络;后者是NVIDIA定制的“性能怪兽”,依托NVLink/RDMA实现GPU间纳秒级同步。文章以AllReduce等通信原语为切入点,对比其架构差异、适用场景与底层原理,并揭示分布式训练中通信瓶颈、拓扑感知、计算-通信重叠等关键工程实践,助开发者穿透框架表层,直抵算力调度本质。(239字)
191 6
|
9天前
|
存储 人工智能 API
部署 OpenClaw 双层记忆系统实战:Mem0+Qdrant向量检索+Markdown持久化搭建教程
在AI智能体实际使用中,**记忆能力**直接决定体验上限。传统上下文窗口有限、历史对话易丢失、关键信息无法长期留存,导致每次交互都要重复说明需求。OpenClaw结合Mem0与Qdrant构建的**双层记忆体系**,完美解决这一问题:上层基于向量数据库实现语义检索与长期记忆,下层通过Markdown文件做关键数据持久化备份,兼顾检索效率与数据安全。
534 5
|
9天前
|
人工智能 Linux API
阿里云+本地全平台部署OpenClaw|iMessage集成+大模型千问/Coding Plan API+避坑指南
2026年,AI自动化框架OpenClaw(原Clawdbot)凭借云端+本地双部署、多模型兼容与iMessage深度集成能力,成为连接苹果生态与AI能力的核心工具。阿里云提供轻量服务器、ECS、计算巢三种一键部署方案,本地支持MacOS、Linux、Windows11全系统运行,搭配阿里云千问大模型、免费Coding Plan API,可实现iMessage消息收发、自然语言交互、任务自动化执行,满足个人效率管理、移动AI助手、轻量业务开发等场景需求。
169 14
阿里云+本地全平台部署OpenClaw|iMessage集成+大模型千问/Coding Plan API+避坑指南

热门文章

最新文章