网络安全 | 深入了解OAuth 2.0原理
关注:CodingTechWork
OAuth 2.0介绍
OAuth 2.0 是一个授权的开放标准。 它的核心目的是解决第三方应用在不需要获取用户密码的情况下,获得对用户资源的有限访问权限的问题。
简单来说,它解决了 “授权” 问题,而不是 “认证” 问题。
- 授权(Authorization):决定“你能做什么”。例如,一个打印服务是否有权访问你在云盘里的特定照片。
- 认证(Authentication):确认“你是谁”。例如,用账号密码登录你的云盘账户。
为了更好地理解,我们来看一个经典的比喻:
打个比方
想象一下你入住一家酒店:
- 你(资源所有者) 在前台出示身份证(认证),证明你是你。
- 前台(授权服务器)给你一张门卡(访问令牌)。
- 这张门卡有特定的权限:在特定时间内(令牌有效期),可以进入特定的房间(资源范围),但不能打开健身房(有限的权限)。
- 你不需要把身份证抵押给酒店,也不需要告诉酒店你的家门钥匙在哪。
OAuth 2.0就是这个流程的数字化版本。你授权一个第三方应用(比如“网易云音乐”)访问你在另一个服务(比如“微信好友列表”)中的特定信息,而无需告诉“网易云音乐”你的微信密码。
核心角色
在OAuth 2.0的流程中,涉及四个关键角色:
- 资源所有者(Resource Owner):通常就是用户本人,拥有受保护资源并能够授权客户端访问这些资源。
- 客户端(Client):想要访问用户资源的第三方应用。例如,想导入你微信好友列表的“网易云音乐”。
- 资源服务器(Resource Server):存储用户资源的服务器。例如,存储了你个人资料和好友列表的微信服务器。
- 授权服务器(Authorization Server):验证用户身份并颁发令牌(Token)的服务器。它负责在用户认证和同意授权后,向客户端发放访问凭证。注意,授权服务器和资源服务器可以是同一台服务器,也可以是分开的。
- 访问令牌(Access Token):客户端用于访问资源服务器上受保护资源的凭证。
令牌(Token)
OAuth 2.0的核心是使用令牌(Token) 来代替用户的密码。
- 访问令牌(Access Token):客户端用来访问资源服务器的凭证。它是一个字符串,代表了客户端被授予的权限。令牌有作用域(Scope) 和有效期(Expires In)。
- 刷新令牌(Refresh Token):当一个访问令牌过期后,客户端可以使用刷新令牌向授权服务器申请一个新的访问令牌,而无需让用户再次授权。
令牌 vs 密码
- 范围有限:令牌只能访问特定的资源(如只读好友列表),而密码拥有全部权限。
- 可以撤销:用户可以随时在授权服务器上撤销对某个客户端的授权,使其令牌立即失效,而无需修改密码。
- 有时间限制:令牌会过期,增加了安全性。
授权码原理
授权码模式是最安全、最常用的流程,适用于有后端服务器的Web应用。其完整时序流程如下:
1. 授权请求
用户点击客户端应用(如网易云音乐)的“通过微信登录”。客户端将用户重定向到授权服务器的授权端点,并携带以下关键参数:
response_type=code:表示请求一个授权码。client_id:客户端在授权服务器注册时获得的ID。redirect_uri:授权成功后跳转回的地址。scope:请求的权限范围(如:读取好友列表)。state:一个随机生成的防CSRF攻击的字符串。
2. 用户认证与授权
用户在授权服务器(微信)的页面上进行登录(如果未登录),并看到一个授权同意页面,询问是否允许“网易云音乐”访问你的好友列表。
3. 颁发授权码
用户点击“同意”后,授权服务器将用户浏览器重定向到第一步指定的 redirect_uri,并在URL的查询参数中附带一个授权码(Authorization Code)。
4. 交换访问令牌
客户端应用的后端服务器(而不是浏览器前端)使用收到的授权码,加上自己的 client_secret,直接向授权服务器的令牌端点发起请求。授权服务器验证通过后,返回一个 访问令牌(Access Token) 和一个可选的 刷新令牌(Refresh Token)。因为最关键的访问令牌是在后端服务器之间传输的,永远不会暴露给用户的浏览器,从而避免了令牌被恶意脚本或中间人窃取。
5. 访问资源
客户端现在可以使用访问令牌,通过调用资源服务器的API来获取受保护的资源(如微信好友列表)。令牌通常被放在HTTP请求的 Authorization 头中。
其他授权模式
OAuth 2.0还定义了其他几种模式,用于不同的场景:
- 隐式模式(Implicit):适用于纯前端应用(如单页应用)。直接返回访问令牌,跳过授权码步骤。安全性较低,已被现代最佳实践(PKCE,Proof Key for Code Exchange)所取代。
- 密码模式(Resource Owner Password Credentials):用户直接将用户名和密码交给客户端应用。这违背了OAuth的初衷,仅适用于高度信任的客户端(如官方应用),不推荐使用。
- 客户端模式(Client Credentials):用于客户端访问自己拥有的资源,而不是用户资源。属于服务器对服务器的通信。
OAuth 2.0安全防护机制
使用最新安全最佳实践
OAuth 2.0安全最佳实践当前规范(RFC 9700)已于2025年1月发布,它更新并扩展了之前的威胁模型和安全建议。关键建议包括:
-
弃用隐式授权模式:隐式授权模式因安全风险已被标记为不推荐使用。
-
推荐使用授权码模式与PKCE:特别是对于单页应用和原生应用。
强化重定向URI验证
严格验证重定向URI是防止许多OAuth攻击的关键:
-
在客户端注册时完整注册所有重定向URI。
-
授权服务器必须确保授权请求中的重定向URI与注册的URI完全匹配。
-
拒绝使用通配符域或过于宽松的URI模式。
实施PKCE
PKCE(RFC 7636)为授权码流程提供了额外的安全层,特别保护公共客户端(如移动应用和单页应用)。
PKCE流程包括:
-
客户端创建
code_verifier(随机字符串)和code_challenge(其变换值)。 -
在授权请求中包含
code_challenge和code_challenge_method。 -
在令牌请求中包含原始的
code_verifier,授权服务器验证其与之前的code_challenge匹配。
规范化HTTP头部处理
针对头部走私漏洞,应采取以下防护措施:
-
更新更高版本,默认规范化头部名称。
-
在上下游服务中实施一致的头部规范化策略,避免对连字符和下划线的差异化处理。
多因素认证与权限最小化
-
实施MFA:虽然OAuth攻击可以绕过传统密码安全,但启用多因素认证仍能提供额外保护层。
-
遵循权限最小化原则:应用程序只请求完成功能所必需的最小权限,减少攻击面。
安全配置与监控
-
定期审查授权应用:用户和管理员应定期检查已授权的OAuth应用,撤销不再使用或不信任的应用。
-
实施令牌生命周期管理:使用短期访问令牌和长期刷新令牌,并确保刷新令牌具有适当的过期时间。
-
加强客户端认证:对于机密客户端,确保使用安全的客户端认证方法,并安全存储客户端密钥。
