使用 PKCE 的授权代码流如何比没有 client_secret 的授权代码流更安全
Posted
技术标签:
【中文标题】使用 PKCE 的授权代码流如何比没有 client_secret 的授权代码流更安全【英文标题】:How can Authorization Code Flow with PKCE be more secure than Authorization Code Flow without client_secret 【发布时间】:2021-05-08 14:22:18 【问题描述】:很可能我误解了有关此主题的某些内容,或者在实施过程中遗漏了某些内容
我浏览了 Auth0 的文档,通过端点而不是 SDK 创建使用 PKCE 的授权代码流,我看到我们提出了如下挑战和验证器(来自 auth0 doc):
// Dependency: Node.js crypto module
// https://nodejs.org/api/crypto.html#crypto_crypto
function base64URLEncode(str)
return str.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
var verifier = base64URLEncode(crypto.randomBytes(32));
和
// Dependency: Node.js crypto module
// https://nodejs.org/api/crypto.html#crypto_crypto
function sha256(buffer)
return crypto.createHash('sha256').update(buffer).digest();
var challenge = base64URLEncode(sha256(verifier));
然后我们将挑战传递给授权端点,如下所示(来自 auth0 doc):
https://YOUR_DOMAIN/authorize?
response_type=code&
code_challenge=CODE_CHALLENGE&
code_challenge_method=S256&
client_id=YOUR_CLIENT_ID&
redirect_uri=YOUR_CALLBACK_URL&
scope=SCOPE&
audience=API_AUDIENCE&
state=STATE
并将代码和验证器传递给令牌端点,如下所示(再次来自 auth0 doc):
curl --request POST \
--url 'https://YOUR_DOMAIN/oauth/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data 'client_id=YOUR_CLIENT_ID' \
--data code_verifier=YOUR_GENERATED_CODE_VERIFIER \
--data code=YOUR_AUTHORIZATION_CODE \
--data 'redirect_uri=https://YOUR_APP/callback'
实现是一件相当简单的事情,但我不明白为什么另一个应用程序不能进行相同的挑战和验证并模拟我们的应用程序?
我认为我们不使用 client_secret 作为授权代码流,暴露的 client_secret 使黑客更容易尝试生成令牌和虚假模拟我们的应用程序,为什么他们不能简单地模拟挑战和验证者?
【问题讨论】:
【参考方案1】:PKCE 就是验证发起初始身份验证请求的客户端是否也是使用授权码获取真实令牌的客户端。
PKCE 是在身份提供者端实施的保护检查,与需要客户端进行检查的状态/随机数安全功能相比。
PKCE 与客户端机密完全无关。
【讨论】:
谢谢您的回答,我知道这与client_secret无关我正在尝试了解这两个之间的安全性比较,我不确定使用它的目的是什么,所以它基本上与跨域或类似攻击无关,我们只是验证授权的同一用户正在发布令牌 是否有任何最佳实践文章可以推荐给我来实现这一点?因为在我的测试过程中,我将 Verifier 和 Code_challenge 暂时存储在本地存储中,直到生成令牌,我确信有更好的替代方法 如果它是用于生产用途,我不会自己实现它,对于生产我会使用github.com/IdentityModel/oidc-client-js 或类似的现成库。 PKCE 自己实现并不难。您只需要将 Verifier 存储在 cookie 或本地存储中。 自己做的最难的教训是 code_verifier 必须至少有 43 个字符长。请参阅 tools.ietf.org/html/rfc7636 的规范。这是否使我的答案成为可接受的答案? 从一开始就可以接受,谢谢【参考方案2】:如果您在应用程序或 SPA 中使用没有 PKCE 的授权代码流,并且有人捕获了您从授权服务器收到的授权代码,他将能够从授权中检索访问令牌通过将授权码 + 客户端 ID(密钥)和客户端密码发送到授权服务器来获取令牌。因为对于您应用的所有用户/客户,ID 和密码相同。然后,他可以使用访问令牌从资源服务器检索用户数据。
如果您使用PKCE 的授权码流,攻击者无法使用授权码,因为他没有验证者。如果他创建自己的验证程序和代码挑战并构建自己的应用程序版本,他还需要让用户使用他的应用程序版本。只有在用户登录到授权服务器后,挑战和验证者才会匹配。 如果他只是以某种方式捕获了授权代码,那么生成自己的挑战和验证者是没有用的,因为流程是从您的应用创建的挑战开始的,并且与他创建的验证者不匹配。
与本题相关:Can't an attacker also get the code challenge?
What is PKCE trying to do?
【讨论】:
感谢您的详细解释,我昨天又看了几篇文章,现在正在使用 PKCE,因为它确实使更多场景。但是您的解释实际上以非常直接的方式总结了整个事情并分享了文章希望它对可能遇到此问题的其他人也有所帮助【参考方案3】:事实并非如此。使用 PKCE 的身份验证代码仅比不涉及客户端密码的隐式流更安全。
PKCE 是一种实现更安全的授权代码流的方法(否则需要客户端密码)
【讨论】:
抱歉延迟回复,我们目前正在为前端做一个后端,我们正在使用客户端机密,但同时发送挑战并验证它以上是关于使用 PKCE 的授权代码流如何比没有 client_secret 的授权代码流更安全的主要内容,如果未能解决你的问题,请参考以下文章
在 PKCE 增强的授权代码流中保护 code_verifier 的最佳实践
在带有 PKCE 的 OAuth 授权流中使用时如何在 Azure 应用注册中启用 CORS?
如何配置 keycloak-(nodejs-)connect 以使用 PKCE?