为什么oauth 2.0规范里 先后两次提交并验证redirect_uri

OAuth 2.0规范要求在获取access token时验证redirect_uri,以防止授权码被拦截导致的安全风险。redirect_uri是接收authorization code的关键,一旦被篡改,攻击者可能利用code冒充合法用户。验证机制在code被泄露后提供补救,确保redirect_uri与之前记录的一致,保护用户免受session劫持。不同服务商对redirect_uri的管理方式各异,有的仅接受注册时填写的地址,有的允许特定子目录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

耗子写了篇关于 oauth 的文章,其中第二个bug没有看懂。翻了原文又翻了规范,后来才想通。

原文是 Bug 2. Lack of redirect_uri validation on get-token endpoint 换token(指的是access token)的时候缺少重定向地址的校验。

OAuth 2.0的规范 http://tools.ietf.org/html/rfc6749#section-4.1 也提到必须校验:

(E) The authorization server authenticates the client, validates the
authorization code, and ensures that the redirection URI
received matches the URI used to redirect the client in
step (C).

redirect_uri这个重定向地址是让第三方接收authorization code(授权码) 来换access token的。对于第三方而言,谁给它授权码谁就是合法用户,后续将与之建立http会话回吐用户的信息。所以一旦这个地址被攻击者改了,code就会被拦截,真正的用户被重定向到了攻击者的页面,正常流程因此中断;而攻击者就可以拿着code重新拼装好redirect_uri往浏览器里一贴,无需密码他就成了合法用户,完成了session劫持。

redirect_uri是如此敏感,有个办法可以在它leak(也就是被改掉)之后补救:第三方在换token的时候是拿着用户给的code,加上自己受信的redirect_uri一起提交给服务提供方做验证。如果之前服务提供方在前面返回code的时候,code是基于异常的redirect_uri计算出来的,那么这一步重新校验就可以知道两者不匹配。

Egor在这儿说redirect_uri应该是个常量,看了下各家都严格做了限定。国内的qq豆瓣是固定用第三方注册时填写的地址;google是可以注册时填多个,但必须使用其中一个;github是必须使用注册时的地址,或该地址的子目录(因此给了攻击者机会)。


### OAuth 2.0 实现方式、原理、流程与示例 #### 什么是 OAuth 2.0OAuth 2.0 是一种授权框架,允许第三方应用程序代表用户访问受保护资源而无需暴露用户的凭证。它通过定义一系列标准化的协议和流程来实现安全性和灵活性。 --- #### OAuth 2.0 的核心原理 OAuth 2.0 的核心在于将 **身份验证** 和 **授权** 解耦开。其主要目标是让客户端能够获得有限制的访问权限到服务器上的资源,而不必获取用户的密码或其他敏感信息。这一过程依赖于令牌机制(Token-Based Authentication),即通过发放访问令牌(Access Token)给客户端完成授权操作[^1]。 --- #### OAuth 2.0 的基本流程 以下是 OAuth 2.0 的通用授权流程: 1. 客户端请求用户授权。 2. 用户被重定向至授权服务器进行登录确认授权范围。 3. 如果用户同意,则授权服务器返回一个授权码(Authorization Code)或者直接返回访问令牌。 4. 客户端使用该授权码向授权服务器交换访问令牌。 5. 访问令牌随后用于访问受保护资源。 具体流程因不同的授权模式而异,常见的有四种授权模式:隐式模式、密码模式、客户端凭据模式以及授权码模式。 --- #### 授权码模式详解 授权码模式是最常用的一种 OAuth 2.0 授权模式,适用于具有后端的服务端应用。它的特点如下: - 更加安全,因为访问令牌不会直接传递给浏览器。 - 需要两次网络通信才能最终获取访问令牌。 以下是授权码模式的具体流程描述: 1. 客户端引导用户跳转到授权服务器的授权页面。 2. 用户输入凭据通过授权界面批准客户端申请的权限。 3. 授权服务器响应一个临时的授权码,将其发送回客户端指定的回调地址。 4. 客户端携带此授权码向授权服务器发起 POST 请求以换取访问令牌。 5. 成功后,授权服务器会返回访问令牌及相关元数据(如刷新令牌 Refresh Token)。 这种模式特别适合那些拥有自己服务端的应用程序开发场景[^3]。 --- #### 设备授权流程概述 设备授权流程是一种专门为低功率或无内置浏览器设备设计的新颖解决方案,在 IoT 场景下尤为适用。当这些受限设备无法方便地打开网页时,可以通过以下步骤完成授权: 1. 设备提示用户前往特定 URL 输入验证码。 2. 同时,设备周期性轮询授权服务器查询状态更新直到收到成功信号为止。 3. 最终由用户手动介入配合完成整个认证环节。 更多细节可参阅基于 Spring 技术栈构建的实际案例演示项目链接说明部分。 --- #### 示例代码展示 下面提供了一个简单的 Python 脚本来模拟如何利用 `requests` 库调用 API 获取 Access Token 的例子: ```python import requests def get_access_token(client_id, client_secret, authorization_code, redirect_uri, token_endpoint): payload = { 'grant_type': 'authorization_code', 'code': authorization_code, 'redirect_uri': redirect_uri, 'client_id': client_id, 'client_secret': client_secret } response = requests.post(token_endpoint, data=payload) if response.status_code == 200: return response.json().get('access_token') else: raise Exception(f"Error fetching access token: {response.text}") # Example usage (replace placeholders with actual values) token = get_access_token( client_id='your_client_id', client_secret='your_client_secret', authorization_code='auth_code_received_from_server', redirect_uri='http://localhost/callback', token_endpoint='https://example.com/oauth/token' ) print(f'Access Token: {token}') ``` 上述脚本展示了如何通过 Authorization Code 来请求 Access Token 的逻辑结构。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值