在使用 OAuth2的资源所有者密码凭据授予类型时,如何对客户端凭据保密

我们正在构建一个 rest 服务,希望使用 OAauth 2进行授权。现行汇票(5月19日的 v2-16)描述了 四种资助类型。它们是获取授权(访问令牌)的机制或流。

  1. 授权码
  2. 隐性拨款
  3. 资源所有者证书
  4. 客户资格证明

看来我们需要支持他们四个,因为他们有不同的目的。前两个(也可能是最后一个)可以从需要访问 API 的第三方应用程序中使用。授权代码是授权 Web 应用程序的标准方式,这些应用程序足够幸运地驻留在一个安全的服务器上,而隐式授权流则是不能完全保密其凭证的客户端应用程序(例如移动/桌面应用程序,JavaScript 客户端等)的选择。
我们希望自己使用第三种机制来为移动设备提供更好的用户体验——而不是让用户在浏览器中进入登录对话框等等,用户只需在应用程序中直接输入他或她的用户名和密码,然后登录。 我们还希望使用客户端凭据授予类型来获取访问令牌,该令牌可用于查看公共数据,而不与任何用户关联。在这种情况下,这不是那么多的授权,而是类似于 API 密钥的东西,我们使用这个密钥只给那些已经在我们这里注册的应用程序提供访问权限,如果需要,我们可以选择撤销访问权限。

所以我的问题是:

  1. 你认为我是否正确理解了不同资助类型的目的?
  2. 你怎么能对你的客户资格保密呢?在第三种和第四种情况下,我们需要在客户机上的某个地方保存客户机 ID 和客户机机密,这听起来不是一个好主意。
  3. 即使您使用了隐式授权类型,并且没有公开您的客户机机密,又是什么阻止了其他应用程序使用相同的授权机制和您的客户机 ID 来模拟您的应用程序呢?

总之,我们希望能够使用来自客户端应用程序的客户端凭据和资源所有者凭据流。这两个流都需要以某种方式存储客户机机密,但客户机是移动应用程序或 JavaScript 应用程序,因此这些机密很容易被窃取。

20947 次浏览

我也面临着类似的问题,而且我对 OAuth 也比较陌生。我已经在我们的 API 中实现了“资源所有者密码凭证”,以供我们的官方移动应用程序使用——网络流程似乎在移动平台上使用起来非常糟糕,一旦用户安装了一个应用程序并相信它是我们的官方应用程序,他们应该感到舒适的输入用户名/密码直接进入应用程序。

正如您所指出的,问题在于我的 API 服务器无法安全地验证应用程序的 client _ id。如果我在应用程序代码/包中包含 client _ secret,那么它就会暴露给安装应用程序的任何人,所以要求 client _ secret 不会使进程更加安全。因此,基本上,任何其他应用程序都可以通过复制 client _ id 来模拟我的应用程序。

直接回答你们的问题:

  1. 我一直在重新阅读规范的不同草案,看看是否有什么变化,并且主要集中在资源所有者密码凭证部分,但我认为你在这些方面是正确的。客户认证(4)我认为也可以用于内部或第三方服务,可能需要访问的不仅仅是“公共”信息,比如你可能有分析或需要获取所有用户信息的东西。

  2. 我觉得你不能对客户保密。

  3. 没有什么能阻止别人使用你的客户身份。这也是我的问题。一旦您的代码离开服务器,或者作为应用程序安装,或者作为 Javascript 在浏览器中运行,您就不能假定任何事情都是秘密的。

对于我们的网站,我们有一个类似的问题,你描述与客户端凭证流程。我最后所做的是将身份验证移动到服务器端。用户可以使用我们的 Web 应用程序进行身份验证,但是我们 API 的 OAuth 令牌存储在服务器端,并且与用户的 Web 会话相关联。Javascript 代码发出的所有 API 请求实际上都是对 Web 服务器的 AJAX 调用。因此浏览器不是直接通过 API 进行身份验证,而是通过一个经过身份验证的 Web 会话。

似乎您的客户端凭证用例是不同的,因为您讨论的是第三方应用程序,并且只通过这种方法提供公共数据。我认为你的担心是有道理的(任何人都可以窃取和使用任何人的 API 密钥) ,但如果你只需要一个免费注册获得一个 API 密钥,我不明白为什么有人真的想要偷一个。

您可以监视/分析每个 API 密钥的使用情况,以试图检测滥用情况,此时您可以使一个 API 密钥失效,并给合法用户一个新的。这可能是最好的选择,但是它不安全。

如果你想把它锁得更紧一点,你也可以使用一个刷新令牌式的方案,虽然我不知道你真的会得到多少。如果您每天过期一次 JavaScript 公开的 api 令牌,并要求第三方使用(秘密的)刷新令牌进行某种服务器端刷新,那么被盗取的 api 令牌永远不会超过一天。可能会鼓励潜在的代币小偷只是注册。但对其他人来说有点痛苦,所以不知道这是否值得。