当前位置: 首页 > news >正文

让 OAuth 授权码流程更安全的 PKCE 技术详解

目录

PKCE 要解决的核心问题是什么?

PKCE 的工作原理

为什么 PKCE 是有效的?

小结


PKCE,全称为 Proof Key for Code Exchange(发音类似 "pixy"),是 OAuth 2.0 的一个关键安全扩展,定义在 RFC 7636 中。PKCE 技术最初是为保护移动和单页应用(SPA)这类“公共客户端”而设计的,但由于其显著的安全优势,现已被视为对所有类型客户端都适用的最佳实践,并在 OAuth 2.1 中成为强制要求。

PKCE 要解决的核心问题是什么?

要理解 PKCE,首先要明白它要防范的攻击——授权码拦截攻击 (Authorization Code Interception Attack)

在标准的 OAuth 2.0 授权码流程中,存在一个短暂的窗口期,攻击者有可能截获到授权码(Authorization Code)。这种情况在移动设备上尤其常见,恶意应用可以注册一个自定义的 URL Scheme,从而拦截从浏览器返回给合法应用的授权码。

攻击流程如下:

  1. 恶意应用启动授权流程: 恶意应用使用合法应用的 client_id 在用户浏览器中发起授权请求。
  2. 用户授权: 用户在授权服务器上登录并同意授权,以为是在给合法应用授权。
  3. 授权码被拦截: 授权服务器将授权码通过重定向方式发送回合法应用。此时,恶意应用通过事先注册的 URL Scheme 拦截了这个重定向请求,从而窃取到了授权码。
  4. 恶意应用交换令牌: 恶意应用拿到授权码后,立即向令牌端点(Token Endpoint)发起请求,用授权码交换访问令牌(Access Token)。
  5. 攻击成功: 由于公共客户端(如手机App)没有客户端密钥(Client Secret)来验证自己,令牌端点仅凭授权码就颁发了访问令牌。恶意应用自此获得了访问用户受保护资源的权限。

问题的关键在于:仅凭授权码,不足以证明交换令牌的客户端就是最初发起请求的那个客户端。

PKCE 的工作原理

PKCE 技术的核心思想是一次性密码,即在授权流程中动态地创建一个只有合法客户端才知道的信息,并用它来证明自己的身份。PKCE 需要引入两个关键参数:

  • code_verifier: 一个高熵的、加密安全的随机字符串。可以理解为客户端创建的临时“密码”。这个值只存在于客户端,绝不能在网络中直接传输。
  • code_challenge: 由 code_verifier 经过特定算法转换而来的字符串。可以理解为对上述“密码”进行哈希或摘要后生成的密码提示。

PKCE 的详细工作流程如下:

第一步:客户端发起授权请求

  1. 生成 code_verifier: 在发起授权请求之前,客户端首先在本地生成一个随机的 code_verifier。例如:dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
  2. 生成 code_challenge: 客户端选择一个转换算法(code_challenge_method),通常是 S256 (即 SHA-256 哈希后进行 Base64url编码),然后根据 code_verifier 生成 code_challenge。假如 code_challenge = BASE64URL-ENCODE(SHA256(code_verifier)),例如:E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  3. 发送授权请求: 客户端将 code_challenge 和 code_challenge_method 作为参数,随授权请求一起发送给授权服务器的授权端点(Authorization Endpoint)。
GET /authorize?
response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&scope=read
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256注意: 此时发送的是 code_challenge(密码提示),而不是 code_verifier(原始密码)。

第二步:授权服务器处理并返回授权码

  1. 存储 code_challenge: 授权服务器收到请求后,会存储 code_challenge 和 code_challenge_method,并将它们与将来要颁发的授权码进行关联。
  2. 用户授权: 用户登录并同意授权。
  3. 返回授权码: 授权服务器将授权码(code)通过重定向方式返回给客户端。

HTTP/1.1 302 Found
Location: YOUR_REDIRECT_URI?code=SplxlOBeZQQYbYS6WxSbIA

第三步:客户端使用授权码交换访问令牌

发起令牌交换请求: 客户端收到授权码后,向授权服务器的令牌端点(Token Endpoint)发起 POST 请求。在此次请求中,客户端必须包含上一步返回的授权码,并且必须附上在第一步中生成的原始 code_verifier。

POST /token
Content-Type: application/x-www-form-urlencodedgrant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=YOUR_REDIRECT_URI
&client_id=YOUR_CLIENT_ID
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk注意: 这是 code_verifier(原始密码)唯一一次在网络中传输,并且是直接发送给令牌端点,不会经过浏览器重定向。

第四步:授权服务器验证并颁发令牌

  1. 验证 code_verifier: 令牌端点收到请求后,会根据之前存储的 code_challenge_method(例如 S256),对请求中收到的 code_verifier 执行相同的转换算法。
  2. 比较结果: 将转换后的结果与之前随授权码一起存储的 code_challenge 进行比较。VERIFY(code_verifier) == code_challenge ?
  3. 颁发令牌:如果两者匹配,说明这个请求确实是由最初发起授权流程的那个客户端发送的。授权服务器验证通过,正常颁发访问令牌和刷新令牌。如果不匹配,说明授权码可能被拦截了,因为攻击者无法提供正确的 code_verifier。授权服务器将拒绝请求,并且立即使被盗用的授权码失效。

为什么 PKCE 是有效的?

PKCE 的有效性在于将授权流程分成了两个部分,并为令牌交换环节增加了一个动态的、一次性的验证凭据。

  • 攻击者即使能拦截到授权码 (code),也无法获取到原始的 code_verifier。
  • code_verifier 不会像授权码那样经过浏览器重定向,而是通过客户端与令牌端点之间的直接、安全的后端信道传输。
  • 由于哈希算法(如 SHA-256)的单向性,攻击者无法通过 code_challenge 反推出 code_verifier。

因此,只有真正的客户端才能同时提供有效的授权码和与之匹配的 code_verifier,从而成功换取访问令牌。

小结

特性

描述

核心目的

防止授权码拦截攻击,确保只有合法的客户端才能用授权码交换令牌。

关键参数

code_verifier (客户端秘密) 和 code_challenge (公开的“挑战”)。

工作流程

客户端在授权请求中发送 code_challenge,在令牌请求中发送 code_verifier。

安全性

code_verifier 的秘密性 和 哈希算法的单向性保证了攻击者无法伪造请求。

当前地位

OAuth 2.1 强制要求,被视为所有 OAuth 2.0 实现的最佳安全实践。

通过强制要求使用 PKCE,OAuth 2.1 大大提升了安全性,简化了开发者的选择,能够更轻松地构建起稳固、安全的授权系统。

http://www.lryc.cn/news/607245.html

相关文章:

  • linux下非Docker模式部署Xinference并部署Rerank模型
  • 最新docker国内镜像源地址大全
  • DreamBoards 借助 DreamHAT+ 雷达插件为 Raspberry Pi 提供 60GHz 毫米波雷达
  • 基于STM32+FPGA工业打印机运动控制卡的核心解决方案
  • Spring Boot微服务性能优化实践指南:从配置到监控
  • MT Photos图库部署详解:Docker搭建+贝锐蒲公英异地组网远程访问
  • 无人机模式的切换
  • PendingIntent相关流程解析
  • 我的博客系统测试报告
  • PHP转Java笔记
  • 前端图片懒加载的深度指南:从理论到实战
  • 浏览器环境segmentit实现中文分词
  • windows内核研究(软件调试-调试事件采集)
  • 性能测试-性能测试中的经典面试题一
  • Nginx跨域问题与 MIME 类型错误深度排错指南:解决 MIME type of “application/octet-stream“ 报错
  • CAN通信协议
  • 从零到英雄:掌握神经网络的完整指南
  • 大模型开发框架LangChain之构建知识库
  • YOLOv8/YOLOv11 C++ OpenCV DNN推理
  • 深入浅出理解WaitForSingleObject:Windows同步编程核心函数详解
  • 大模型幻觉的本质:深度=逻辑层次,宽度=组合限制,深度为n的神经网络最多只能处理n层逻辑推理,宽度为w的网络无法区分超过w+1个复杂对象的组合
  • 前沿智能推荐算法:基于多模态图神经网络的隐私保护推荐系统
  • JS字符串匹配,检测字符中是否包含ABC,includes,indexOf
  • 网络配置+初始服务器配置
  • C++ AI 实用案例强化学习
  • UE5多人MOBA+GAS 番外篇:同时造成多种类型伤害,以各种属性值的百分比来应用伤害(版本二)
  • MySQL常见的聚合函数:
  • 逻辑回归----银行贷款模型优化
  • 【C++/STL】vector基本介绍
  • git pull和git fetch的区别