OAuth 2.0授权码模式和OAuth 2.1 授权码+PKCE模式比较
OAuth 2.0 与 OAuth 2.1 的区别
1. 背景
- OAuth 2.0:发布于 2012 年(RFC 6749),是目前广泛使用的授权框架。
- OAuth 2.1:并非一个全新的协议,而是对 OAuth 2.0 的安全强化和最佳实践整合。它由 OAuth 工作组在 2021 年左右提出(目前仍是草案,但已被广泛采纳为事实标准)。
📌 注意:OAuth 2.1 并不是 RFC,而是对 OAuth 2.0 多个扩展(如 PKCE、Bearer Token 安全性等)的整合与弃用不安全实践的总结。
2. 主要区别
| 特性 | OAuth 2.0 | OAuth 2.1 |
|---|---|---|
| 隐式模式(Implicit Grant) | ✅ 支持(response_type=token) |
❌ 明确弃用(因安全风险) |
| 密码模式(Resource Owner Password Credentials) | ✅ 支持 | ❌ 弃用(仅限遗留系统) |
| 客户端凭证模式(Client Credentials) | ✅ 保留 | ✅ 保留(用于服务间通信) |
| 授权码模式(Authorization Code) | ✅ 支持 | ✅ 强制要求配合 PKCE(即使 confidential client 也推荐) |
| PKCE(Proof Key for Code Exchange) | 可选扩展(RFC 7636) | ✅ 强制要求所有客户端使用 |
| 重定向 URI 要求 | 建议严格匹配 | ✅ 必须精确匹配(防止开放重定向攻击) |
| State 参数 | 推荐使用 | ✅ 必须使用(防 CSRF) |
| 令牌传输安全性 | 建议 HTTPS | ✅ 强制要求 HTTPS |
3. 核心理念变化
- OAuth 2.1 的目标是:“默认安全”。
- 它移除了历史上被证明不安全的授权方式(如隐式模式),并强制使用现代安全机制(如 PKCE)。
- 即使你是 confidential client(有后端、能安全存储 client_secret),OAuth 2.1 也推荐使用 PKCE,以统一实现并防御授权码拦截攻击。
PKCE 模式 vs 授权码模式
这个问题其实有点“类别混淆”——PKCE 不是一种独立的授权模式,而是对授权码模式的增强。
1. 授权码模式(Authorization Code Flow)
适用场景:Web 应用(有后端)、传统 OAuth 2.0。
流程简述:
- 用户访问客户端 → 重定向到授权服务器(带
client_id,redirect_uri,scope,state)。 - 用户登录并授权。
- 授权服务器重定向回客户端,携带
code。 - 客户端后端用
code + client_secret向授权服务器换取access_token。
- 用户访问客户端 → 重定向到授权服务器(带
安全前提:客户端必须是 confidential client(能安全存储
client_secret)。
sequenceDiagram
participant User as 用户浏览器
participant Client as 客户端(Web 后端)
participant AuthServer as 授权服务器 (OAuth 2.0)
User->>Client: 访问受保护资源
Client->>User: 重定向到授权服务器<br/>(含 client_id, redirect_uri, scope, state)
User->>AuthServer: 登录并授权
AuthServer->>User: 重定向回客户端 redirect_uri<br/>(携带 code 和 state)
User->>Client: 浏览器自动跳转,附带 code
Client->>AuthServer: 后端请求 token endpoint<br/>(code + client_id + client_secret + redirect_uri)
AuthServer->>Client: 返回 access_token(可能含 refresh_token)
Client->>User: 使用 access_token 获取用户资源
2. PKCE(Proof Key for Code Exchange)
- 目的:解决 public client(如 SPA、移动 App)无法安全存储
client_secret的问题。 - 核心思想:用动态生成的“代码验证器”(code_verifier)和其哈希(code_challenge)替代
client_secret。
PKCE 流程(叠加在授权码模式上):
- 客户端生成一个随机字符串
code_verifier。 - 对其进行 SHA256 哈希,得到
code_challenge。 - 在第一步授权请求中,带上
code_challenge和code_challenge_method=S256。 - 用户授权后,拿到
code。 - 客户端在兑换 token 时,提交原始的
code_verifier。 - 授权服务器用
code_verifier重新计算哈希,与之前存储的code_challenge比对。
✅ 这样即使攻击者截获了 code,也无法兑换 token(因为没有 code_verifier)。
sequenceDiagram
participant User as 用户浏览器 / App
participant Client as 客户端(前端或 public client)
participant AuthServer as 授权服务器 (支持 PKCE)
Note over Client: 1. 生成 code_verifier (随机字符串)<br/>2. 计算 code_challenge = BASE64URL(SHA256(code_verifier))
User->>Client: 发起登录
Client->>AuthServer: 重定向到授权端点<br/>(client_id, redirect_uri, scope, state,<br/>code_challenge, code_challenge_method=S256)
User->>AuthServer: 登录并授权
AuthServer->>User: 重定向回 redirect_uri<br/>(携带 code 和 state)
User->>Client: 收到授权码 code
Client->>AuthServer: 请求 token endpoint<br/>(code + code_verifier + client_id + redirect_uri)
AuthServer->>AuthServer: 验证 code_verifier → 重新计算 SHA256 并比对 code_challenge
AuthServer->>Client: 验证通过,返回 access_token
Client->>User: 使用 access_token 调用 API
3. 关键区别总结
| 维度 | 授权码模式(传统) | 授权码 + PKCE |
|---|---|---|
是否需要 client_secret |
✅ 需要(confidential client) | ❌ 不需要(适用于 public client) |
| 安全性 | 依赖 client_secret 保密 |
依赖动态 code_verifier(每次不同) |
| 适用客户端类型 | Web 后端应用 | SPA、移动 App、桌面应用、甚至 Web 应用(OAuth 2.1 推荐) |
| 是否防授权码拦截 | ❌ 若 code 被截获且攻击者有 client_secret,可盗用 |
✅ 即使 code 被截获,无 code_verifier 也无法使用 |
💡 现代最佳实践(包括 OAuth 2.1):所有授权码流程都应使用 PKCE,无论是否是 public client。
总结
- OAuth 2.1 ≠ 全新协议,而是 OAuth 2.0 的安全加固版,弃用不安全模式,强制 PKCE 和 HTTPS。
- PKCE 不是替代授权码模式,而是其安全增强,用于防止授权码被滥用,尤其适用于无法保密
client_secret的场景。 - 现代应用应一律使用“授权码 + PKCE”,即使是后端服务。
OAuth 2.0授权码模式和OAuth 2.1 授权码+PKCE模式比较
https://itxiaopang.github.io/p/f95e0e64e1804e17ac245f3c696b835f/