3. OAuth2.0 四种授权模式对比:授权码模式、隐式模式、密码模式、客户端凭证模式,以及 PKCE 扩展

OAuth2.0 协议定义了四种核心授权模式,分别适用于不同的客户端类型与安全场景。此外,PKCE(Proof Key for Code Exchange) 作为授权码模式的重要安全扩展,已成为移动端与单页应用的首选方案。本章将从流程、适用场景、安全等级三个维度进行系统对比。

3.1 四种授权模式核心流程对比

下表从参与者、凭证传递方式、令牌获取步骤三个关键维度,对四种模式进行横向对比:

授权模式 典型客户端 用户凭证是否暴露给客户端 是否需要客户端密钥 令牌传递方式 安全等级
授权码模式 Web 服务端应用 否(通过授权码中转) 是 后端通道(Back Channel) ★★★★★
隐式模式 浏览器单页应用(SPA) 否(直接返回令牌) 否 前端通道(Front Channel) ★★★☆☆
密码模式 受信任的第一方应用 是(直接传递用户名密码) 是 后端通道 ★★☆☆☆
客户端凭证模式 服务间通信(M2M) 不涉及用户 是 后端通道 ★★★★☆
安全提示: 隐式模式因令牌直接暴露在浏览器 URL 片段中,已不推荐用于新应用。OAuth2.0 Security BCP(Best Current Practice)建议使用授权码模式 + PKCE 替代隐式模式。

3.2 授权码模式(Authorization Code Grant)

授权码模式是 OAuth2.0 中最完整、最安全的流程。它通过授权码作为临时凭证,在客户端与授权服务器之间建立安全的后端通道,避免访问令牌暴露在用户代理(浏览器)中。

授权码模式核心流程 用户代理 客户端 授权服务器 ① 访问资源 ② 重定向至授权端点 ③ 用户认证并授权 ④ 返回授权码(code) ⑤ 客户端 + code + client_secret ⑥ 返回 access_token ⑦ 使用 access_token 访问资源 关键安全点:授权码通过前端通道传递,但访问令牌始终通过后端通道交换,避免令牌暴露。

3.3 隐式模式(Implicit Grant)

隐式模式专为浏览器单页应用(SPA)设计,授权服务器直接返回访问令牌,省略了授权码交换步骤。由于令牌直接暴露在 URL 片段中,存在令牌泄露和中间人攻击风险。

弃用警告: 根据 OAuth 2.0 Security BCP(RFC 9700),隐式模式已被标记为“不推荐使用”。所有新开发的 SPA 应使用授权码模式 + PKCE。

3.4 密码模式(Resource Owner Password Credentials Grant)

密码模式允许客户端直接收集用户的用户名和密码,并以此向授权服务器换取访问令牌。该模式仅适用于高度信任的第一方应用,例如操作系统级应用或官方移动客户端。

  • 优点: 流程简单,一次请求即可获取令牌。
  • 缺点: 客户端直接接触用户明文密码,一旦客户端被攻破,所有用户凭证将泄露。
  • 适用场景: 迁移旧系统、内部工具、受信任的官方应用。

3.5 客户端凭证模式(Client Credentials Grant)

客户端凭证模式用于服务到服务(M2M)的通信场景,不涉及用户。客户端使用自己的 client_id 和 client_secret 直接向授权服务器请求令牌。

// 客户端凭证模式请求示例
POST /oauth/token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=your_client_id
&client_secret=your_client_secret
&scope=read write
可观测性要点: 在 Mock 服务中,客户端凭证模式是最容易模拟的模式。你可以在 Mock 响应中注入延迟、错误码、限流响应,以测试下游服务的容错能力。

3.6 PKCE 扩展(Proof Key for Code Exchange)

PKCE(RFC 7636)是授权码模式的安全增强扩展,专门解决公共客户端(如移动 App、SPA)无法安全存储 client_secret 的问题。它通过动态生成的 code_verifier 和 code_challenge 替代静态密钥。

PKCE 参数 说明 生成方式
code_verifier 客户端生成的随机字符串(43~128 字符) crypto.randomBytes(32).toString('base64url')
code_challenge code_verifier 的变换值 base64url(sha256(code_verifier))
code_challenge_method 变换方法(S256 或 plain) 推荐使用 S256
授权码模式 + PKCE 扩展流程 客户端(SPA) 授权服务器 资源服务器 ① 生成 code_verifier + challenge ② 授权请求 + code_challenge ③ 返回授权码 ④ 令牌请求 + code_verifier ⑤ 验证 code_verifier ⑥ 返回 access_token ⑦ 使用 access_token 访问资源

3.7 四种模式 + PKCE 选型决策树

在实际项目中,选择哪种授权模式取决于客户端类型、安全要求和用户交互方式。以下决策树可帮助你快速判断:

  1. 是否涉及用户?
    • 否 → 使用 客户端凭证模式
    • 是 → 进入下一步
  2. 客户端是否能安全存储密钥?
    • 是(Web 服务端) → 使用 授权码模式
    • 否(SPA / 移动 App) → 使用 授权码模式 + PKCE
  3. 是否是完全受信任的第一方应用?
    • 是 → 可考虑 密码模式(但优先推荐授权码模式)
    • 否 → 禁止使用密码模式
Mock 服务实战建议: 在构建 OAuth2.0 Mock 服务时,建议优先实现授权码模式 + PKCE 和 客户端凭证模式。这两种模式覆盖了 90% 以上的现代应用场景。密码模式和隐式模式可作为兼容性端点保留,但应在文档中标注为“遗留模式”。