什么是 PKCE:从基本概念到深入理解
本文解释了 PKCE(验证密钥交换)如何通过防止恶意应用程序截取授权码来保护 OAuth 2.0 授权码流程,带你从基本概念到全面理解。
验证密钥交换(PKCE)是 授权码流程 的一个扩展,最初设计是为了在移动应用中保护授权码流程,现在也推荐单页应用使用。从 OAuth 2.1 开始,所有类型的客户端,包括 公共客户端 和 机密(私人)客户端,都强制使用 PKCE。
在本文中,我们将帮助你理解为什么创建 PKCE 以及它如何保护你的应用程序,从而深入理解 PKCE。
为什么需要 PKCE?
在 OAuth 2.0 授权码流程中,用户通过应用程序请求登录。认证服务器将用户重定向到认证页面。用户认证后,服务器将授权码返回给应用程序,然后应用程序使用此代码从认证服务器请求访问令牌。
该流程存在一个重大安全风险:授权码可能被恶意程序截取。在移动设备中,这种风险尤其令人担忧,因为其他应用程序可能注册相同的重定向 URI 并截获授权码。
拦截过程如下图所示:
步骤 (1):应用程序通过无法被截取的安全 API 执行授权请求。在此步骤中,请求者还提供了重定向 URI。
步骤 (2):请求随后被转发到 OAuth 2.0 授权服务器。因为 OAuth 要求使用 TLS,这种通信受 TLS 保护,无法被截取。
步骤 (3):授权服务器返回授权码。
步骤 (4.a):授权码通过步骤 (1) 中提供的重定向 URI 返回给请求者。在此步骤中,如果恶意应用注册自己为重定向 URI 的处理器,那么恶意应用可以截获授权码。利用授权码,攻击者可以分别在步骤 (5.a) 和 (6.a) 中请求并获取访问令牌。
如上所示,在 OAuth 2.0 授权码流程中,如果授权码被截取,攻击者可以利用它获取访问令牌。因此,我们需要一个机制来防止授权码截取,这导致了 PKCE 的创建。
PKCE 如何工作?
如前所述,如果我们想要防止攻击,我们需要确保只有发起请求的应用程序可以请求并获取访问令牌。这就是 PKCE 发挥作用的地方。
PKCE 通过引入“证明密钥”概念解决了这个问题。
在请求授权码时,应用程序首先生成一个随机码验证器并将其存储在本地。然后,它使用特定算法将码验证器转换为码挑战。应用程序在授权码请求时将码挑战和码挑战方法一起发送到认证服务器。
码验证器是一个随机生成的字符串,码挑战通过转换从码验证器派生。有两种转换方法支持:
plain
:直接将码验证器用作码挑战
S256
:对码验证器应用 SHA-256 哈希,然后进行 Base64URL 编码。由于哈希输出无法反演以获取码验证器,并且因为传输中plain
方法可能易受中 间人攻击,出于安全原因,强烈推荐使用S256
。
用户验证后,认证服务器将授权码返回给应用程序。当请求访问令牌时,应用程序将授权码和码验证器一起发送到认证服务器。服务器使用先前接收的“码挑战方法”转换“码验证器”并将结果与先前接收的“码挑战”进行比较,以验证客户端是否持有“码验证器”。
步骤 (1-3):应用程序创建并记录一个名为“码验证器”的密钥,并在 OAuth 2.0 授权请求中派生一个转换版本“码挑战”,以及转换方法“码挑战方法”。
步骤 (3-6):认证服务器正常响应,但记录“码挑战”和“码挑战方法”。
步骤 (7.a):应用程序然后像往常一样将授权码发送到令牌终端,但包含步骤 (1) 中生成的“码验证器”密钥。
步骤 (8.a-9.a):授权服务器将“码验证器”转换为“码挑战”并将其与步骤 (1-3) 中的“码挑战”进行比较。如果它们不相等,将拒绝访问。
在这种情况下,即使恶意应用在步骤 (6.b) 截获了授权码,它也无法兑换为访问令牌,因为它不持有“码验证器”密钥,并且因为“码验证器”是通过 TLS 发送的,无法被截获。
总结
本文解释了 PKCE 的工作原理以及为什么它对保护授权码流程是必要的。通过添加证明密钥机制,PKCE 防止了恶意应用程序截取和滥用授权码。希望这个解释能帮助你深入理解 PKCE。