首页 > 解决方案 > Oauth2.0 授权码授予 ClientId & Secret 混淆

问题描述

我试图了解 OAuth2.0 提供的各种授权类型。我一直在阅读它,并且有很多资源可以很好地详细解释它,例如thisthisthis引用一些。

在授权码授予类型的情况下,据我了解有两个步骤。

第 1 步 - 获取授权码本身

所以让我们假设用户打开了应用程序,比如AwesomeApp在他们的浏览器中。这个应用程序有一个选项,比如用 Facebook 登录,用户选择继续。这将使用查询参数中所需的详细信息向授权服务器(在我们的示例中为 Facebook)发起 GET 请求,例如(取自上面链接的资源之一):

https://authorization-server-of-facebook.com/auth?response_type=code&
  client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos&state=1234zyx

现在我理解了每个参数的含义(再次感谢资源)。我还了解到,在AwesomeApp拨打此电话之前,它必须已在 Facebook 注册以接收客户端 ID 和客户端密码(通过某种方式)。

现在,一旦用户批准请求,facebook 的授权服务器就会通过将用户的浏览器重定向回(在上述请求中)提供的重定向 uri 并使用授权代码来响应上述请求。

第 2 步 - 将授权代码交换为实际访问令牌

现在AwesomeApp需要将上面收到的授权码交换为访问令牌。为此,AwesomeApp会发出如下所示的 POST 请求:

POST https://api.authorization-server-of-facebook.com/token
  grant_type=authorization_code&
  code=AUTH_CODE_RECEIVED_IN_THE_ABOVE_STEP&
  redirect_uri=REDIRECT_URI&
  client_id=CLIENT_ID&
  client_secret=CLIENT_SECRET

对于上述请求,facebook 的授权服务器返回访问令牌、刷新令牌、到期时间等。

现在我的问题在上面的步骤 2 中。这个 POST 不应该是后端调用吗?为什么?因为它也需要在请求中发送客户端密码。如果从前端进行AwesomeApp,很容易泄露给虚假用户。不是吗?

所以我在想,它应该类似于一旦AwesomeApp收到授权码,前端AwesomeApp应该将它发送到它自己的后端,然后AwesomeApp后端应该发出上述 POST 请求,从上述请求的响应,然后将其传递给它的前端。这不应该是这样吗?

现在在我遇到的大多数资源(包括上面的链接)中,它讨论了PKCE Extension每次生成动态客户端密码的讨论。但是,如果 POST(步骤 2 中的那个)仍然是从前端本身完成的,那会更好吗?此外,如果每次都动态生成此客户端机密,那么它也可能由虚假用户完成,不是吗。我的意思是授权服务器如何验证发出请求的客户端确实是它允许的客户端?(在客户端密码的情况下,这是有道理的,因为客户端密码是AwesomeApp由 Facebook 的授权服务器提供的。在这种情况下,它没有,因为这个密码是由客户端自己生成的)。

以上所有的误解是什么?

根据此处解释的流程,在此处输入图像描述如何code_verifier防止对手作为正版应用进行游戏?与客户端密码不同,攻击者永远无法冒充真正的客户端(当然,除非客户端密码本身以某种方式受到损害),在这种情况下,攻击者可以简单地发送任何code_verifier. 在最终响应的令牌请求和验证出现之前code_verifier,授权服务器如何验证授权请求确实来自真正的客户端?

标签: oauthoauth-2.0authorization

解决方案


您正确理解授权码流程。在最初的 OAuth2 规范中,代码流旨在用于机密客户端(即在服务器上运行的传统 Web 应用程序)。隐式流旨在用于在浏览器内运行的应用程序,例如单页应用程序。隐式流通过重定向 URI 直接将访问令牌传递给客户端。

现在隐式流容易受到令牌泄漏(引用标头和服务器日志)的影响,因此发明了PKCE以将代码流也用于公共客户端。它从一个名为的标识符生成一个散列值verifier,并将其与授权请求一起发送。当客户端获得代码时,它使用验证者作为秘密向授权服务器证明是客户端发出了原始授权请求(用户登录到该请求)。

即使恶意客户端可以生成授权请求,用户也需要登录并同意客户端获取访问令牌来访问他们的数据。如果用户决定信任恶意客户端,则协议无能为力,因为客户端不必对自己进行身份验证。


推荐阅读