- Refinition
- 四个核心角色
- 四类常见授权模式
- 授权模式中的术语
- OAuth2 协议流程解析
- 后端之间的交互流程-包含安全方案设计
- 应用注册与安全凭证发放
- OAuth2授权码流程
- 为什么用code不直接返回token?
Refinition
OAuth2 是在WEB基础上发展出来的一个授权框架(Authorization Framework),也可以认为它是一套协议,一套能解决第三方授权问题的解决方案,优势在于它允许第三方应用在不获取用户密码的情况下,获得访问用户资源(用户的ID信息等)的有限权限。
它是如何做到的?下面来解析一下这个协议。
搞懂这个协议,需要理解下面几个部分:
四个核心角色
OAuth2 流程中有四个关键角色:
-
资源所有者 (Resource Owner)
用户(一般指使用客户端的人),他拥有受保护资源(一般指他的账号信息); -
客户端 (Client)
一个前端UI应用,方便用户操作的面板。一般来说客户端和授权服务器是前后端关系。 -
授权服务器 (Authorization Server)
验证用户身份并颁发令牌的 绝对控制者。 -
资源服务器 (Resource Server)
一般指可以提供给用户使用的服务器,能给用户提供专属服务,比如网盘服务、点外卖服务,这种也叫第三方应用。
资源服务器一般需要用户信息,才能提供服务。
获得用户信息,可以让用户注册,但是APP太多了,很多用户不愿意注册了。就发展出第三方应用去授权服务器拿取用户ID的免注册模式。
四类常见授权模式
OAuth2 定义了多种授权方式,适应不同场景,下面看4个常见:
- 授权码模式 (Authorization Code) - 最常用、较安全(本文讨论这个模式)
- 密码模式 (Resource Owner Password Credentials) - 需要信任客户端
- 客户端凭证模式 (Client Credentials) - 应用访问自己的资源
- 隐式模式 (Implicit) - 较不安全,已不推荐
授权模式中的术语
-
令牌 (Tokens)
- 访问令牌 (Access Token):相当于"临时门禁卡",用于访问资源
- 刷新令牌 (Refresh Token):用于获取新的访问令牌,避免用户频繁重新登录
-
......
OAuth2 协议流程解析
在看时序图之前,必须先清楚各个角色的作用,不然就会混乱。
时序图,简版流程:
更接近实际的流程,以企微授权一个工作台应用案例为例子:
以上都是以一个用户视角看的流程,其实后端之间还做了很多事情,才能保障整个流程的安全,不过下面的流程图需要以一个开发者的角度看待,下面继续解构。
后端之间的交互流程-包含安全方案设计
下面以企业微信OAuth2授权码流程,以开发者(应用服务器/资源服务器)的视角,看待应用如何与企微授权服务器建立联系,包括如何获取安全凭证(如Secret)、验证的流程。
企业微信OAuth2授权码流程中,开发者需要先在企微管理后台创建应用,获取应用的安全凭证(corp_id, secret等),然后在应用服务器中使用这些凭证。
整体流程分为两个主要部分:
- 应用注册与安全凭证发放(静态配置)
- OAuth2授权码流程(动态交互)
理解几个密码学上关键的工具包:
- AgentId
- Secret
- 随机数
- 签名-HMAC
- ......
应用注册与安全凭证发放
这一步是确保整体安全的关键流程,Secret参数作为一个关键密钥(可以申请更换),它也是标识身份,防抵赖性作用。
一个AgentId 对应 一把Secret密钥。
Secret必须安全地存储在应用服务器内,只做打签名用。不可以暴露,否则有被冒充安全风险!
OAuth2授权码流程
State:
客户端生成 State 流程:
- 收集数据:随机数 + 时间戳 + 会话ID + 业务参数
- 构建结构:
- 计算签名:HMAC-SHA256(排序后的数据字符串, client_secret)
- 添加签名:
- Base64编码:生成最终的state参数
客户端/服务端验证 State 流程:
- Base64解码state,得到原始数据结构
- 提取签名值,从数据结构中移除签名字段
- 重新计算签名:HMAC-SHA256(相同的排序数据, client_secret)
- 对比签名:恒定时间比较计算签名与提取签名
- 如果一致 → 数据未被篡改,验证通过
- 如果不一致 → 可能被篡改,拒绝请求
再次看OAuth2授权码流程:
为什么用code不直接返回token?
授权码(code)的安全作用介绍:
授权码(code)是OAuth2授权码流程中的核心凭证,它通过前端信道传递(浏览器重定向),然后由客户端应用在后端信道中与授权服务器交换访问令牌。授权码的安全作用主要包括:
- 避免访问令牌通过前端信道传输,降低令牌泄露风险。
- 授权码是短暂的,一次性使用的,降低被窃取后的风险。
- 授权码与客户端身份绑定,防止被其他客户端使用。
假设code被截取:
- 即使授权码被窃取,攻击窗口很短
- 自动清理过期的授权码,减少存储负担