1. OAuth2.0 协议概述
1.1 诞生背景:从“密码共享”到“授权委托”
在 OAuth2.0 出现之前,第三方应用获取用户资源(如社交好友列表、云存储文件)的唯一方式是直接获取用户的账号密码。这种“密码共享”模式存在严重的安全与合规问题:
- 密码泄露风险:第三方应用存储用户密码,一旦数据库泄露,用户所有资产暴露。
- 权限不可控:第三方应用获得的是账号的完整权限,无法限制其仅访问特定资源。
- 无法撤销:用户只能通过修改密码来收回第三方应用的访问权,操作成本高且影响其他正常应用。
- 审计缺失:服务端无法区分请求是来自用户本人还是第三方应用,日志审计形同虚设。
OAuth2.0 协议于 2012 年由 IETF 正式发布(RFC 6749),其核心思想是 “授权委托”:用户(资源所有者)授权第三方应用(客户端)获取一个有限范围、有时效的令牌(Access Token),而非直接交出密码。从此,后端系统可以在不暴露用户凭证的前提下,实现精细化的权限控制与审计追踪。
合规启示: OAuth2.0 的诞生直接回应了 GDPR、等保 2.0 等法规中关于“最小权限”、“访问控制”、“可审计性”的核心要求。在后端审计实践中,令牌的生命周期管理是合规检查的第一道防线。
1.2 核心思想:四个角色与三个关键步骤
OAuth2.0 定义了四个核心角色,它们之间的交互构成了授权的基础框架:
| 角色 | 英文名称 | 后端审计视角说明 |
|---|---|---|
| 资源所有者 | Resource Owner | 通常是用户,拥有资源的最终处置权。审计关注点:用户授权行为的记录。 |
| 客户端 | Client | 需要访问资源的第三方应用。审计关注点:客户端身份(client_id)与授权范围。 |
| 授权服务器 | Authorization Server | 负责认证用户并颁发令牌。审计关注点:令牌颁发日志、授权码生命周期。 |
| 资源服务器 | Resource Server | 托管受保护资源的 API 服务。审计关注点:令牌验证、权限判定、访问日志。 |
协议的核心流程可概括为三个关键步骤:
- 获取授权:客户端引导用户到授权服务器,用户同意后获得一个授权码(Authorization Code)。
- 换取令牌:客户端使用授权码向授权服务器换取访问令牌(Access Token)和可选的刷新令牌(Refresh Token)。
- 访问资源:客户端携带访问令牌向资源服务器请求受保护资源。
1.3 四种授权模式对比
OAuth2.0 定义了四种授权模式(Grant Types),以适应不同的客户端类型和安全场景。在后端合规审计中,选择错误的授权模式是常见的高风险项。
| 授权模式 | 适用场景 | 安全等级 | 令牌存储位置 | 后端审计关键点 |
|---|---|---|---|---|
| 授权码模式 (Authorization Code) |
有后端的 Web 应用、移动 App(配合 PKCE) | ⭐⭐⭐⭐⭐ | 后端服务器 | 授权码一次性使用、client_secret 保护、redirect_uri 校验 |
| 隐式模式 (Implicit) |
纯前端应用(已不推荐,RFC 8252 已废弃) | ⭐⭐ | 浏览器 URL 片段 | 令牌暴露在 URL 中,无法安全存储,审计日志缺失 |
| 密码模式 (Resource Owner Password Credentials) |
高度信任的第一方应用(如官方 App) | ⭐⭐⭐ | 客户端 | 直接接触用户密码,违背“最小权限”原则,审计粒度粗 |
| 客户端凭证模式 (Client Credentials) |
服务器到服务器的 API 调用(无用户参与) | ⭐⭐⭐⭐ | 客户端服务器 | 仅适用于机器间通信,需严格管控 client_secret 和 IP 白名单 |
合规红线: 在等保 2.0 和金融行业监管中,隐式模式因令牌直接暴露在浏览器地址栏,已被明确禁止用于生产环境。密码模式仅在无法使用其他模式且客户端高度可信时允许使用,且必须记录完整的认证日志。
1.4 授权码模式:后端审计的黄金标准
在四种模式中,授权码模式是后端合规审计的首选方案。其核心优势在于:
- 令牌不经过用户代理:授权码通过前端通道传递,而访问令牌通过后端通道(客户端到授权服务器)直接获取,避免了令牌在浏览器或移动端被截获。
- 支持刷新令牌:长期有效的刷新令牌可以安全地存储在服务端,用于在访问令牌过期后静默续期,减少用户交互。
- 完整的审计链路:授权服务器可以记录每一次授权码的颁发、令牌的换取、令牌的刷新和令牌的撤销,形成完整的审计闭环。
审计实践提示: 在后端审计中,应重点检查授权码是否被一次性使用(One-Time Use)、redirect_uri 是否严格匹配白名单、以及是否强制使用了 PKCE(Proof Key for Code Exchange)来防止授权码拦截攻击。