使用 PKCE 的授权代码流如何比没有 client_secret 的授权代码流更安全
How can Authorization Code Flow with PKCE be more secure than Authorization Code Flow without client_secret
很可能我误解了关于这个主题的一些东西或者在实施过程中遗漏了一些东西
我浏览了 Auth0 的文档,通过端点而不是 SDK 使用 PKCE 创建授权代码流,我看到我们提出了如下挑战和验证程序(来自 auth0 文档):
// 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 文档):
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 文档):
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 使黑客更容易尝试生成令牌并错误地模拟我们的应用程序,为什么他们不能简单地模拟挑战者和验证者?
PKCE 就是验证发起初始身份验证请求的客户端是否与使用授权码获取真实令牌的客户端相同。
PKCE 是一种在身份提供者端实施的保护检查,相比之下 State/Nonce 安全功能需要客户端进行检查。
PKCE 与客户端密钥完全无关。
如果您在应用程序或 SPA 中使用没有 PKCE 的 授权代码流,并且有人捕获了您从授权服务器收到的授权代码,他将能够检索到通过将授权代码 + 客户端 ID(密钥)和客户端密码发送到授权服务器,从授权令牌访问令牌。因为您的应用程序的所有 users/clients 的 ID 和密码 相同 。然后他可以使用访问令牌从资源服务器检索用户数据。
如果你使用PKCE授权代码流,攻击者无法使用授权代码,因为他没有验证者。如果他创建自己的验证器和代码挑战并构建他自己的应用程序版本,他还需要让用户使用他的应用程序版本。只有这样,用户登录授权服务器后,质询和验证者才会匹配。 如果他只是以某种方式捕获了授权码,那么生成自己的挑战和验证器是没有用的,因为流程是从您的应用程序创建的挑战开始的,并且与他创建的验证器不匹配。
与此问题相关:
不是。使用 PKCE 的授权代码仅比不涉及客户端机密的隐式流更安全。
PKCE 是一种实现更安全的授权代码流的方法(否则需要客户端密码)
很可能我误解了关于这个主题的一些东西或者在实施过程中遗漏了一些东西
我浏览了 Auth0 的文档,通过端点而不是 SDK 使用 PKCE 创建授权代码流,我看到我们提出了如下挑战和验证程序(来自 auth0 文档):
// 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 文档):
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 文档):
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 使黑客更容易尝试生成令牌并错误地模拟我们的应用程序,为什么他们不能简单地模拟挑战者和验证者?
PKCE 就是验证发起初始身份验证请求的客户端是否与使用授权码获取真实令牌的客户端相同。
PKCE 是一种在身份提供者端实施的保护检查,相比之下 State/Nonce 安全功能需要客户端进行检查。
PKCE 与客户端密钥完全无关。
如果您在应用程序或 SPA 中使用没有 PKCE 的 授权代码流,并且有人捕获了您从授权服务器收到的授权代码,他将能够检索到通过将授权代码 + 客户端 ID(密钥)和客户端密码发送到授权服务器,从授权令牌访问令牌。因为您的应用程序的所有 users/clients 的 ID 和密码 相同 。然后他可以使用访问令牌从资源服务器检索用户数据。
如果你使用PKCE授权代码流,攻击者无法使用授权代码,因为他没有验证者。如果他创建自己的验证器和代码挑战并构建他自己的应用程序版本,他还需要让用户使用他的应用程序版本。只有这样,用户登录授权服务器后,质询和验证者才会匹配。 如果他只是以某种方式捕获了授权码,那么生成自己的挑战和验证器是没有用的,因为流程是从您的应用程序创建的挑战开始的,并且与他创建的验证器不匹配。
与此问题相关:
不是。使用 PKCE 的授权代码仅比不涉及客户端机密的隐式流更安全。
PKCE 是一种实现更安全的授权代码流的方法(否则需要客户端密码)