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

时间:2011-05-31 16:06:12

标签: security oauth-2.0

我们正在建立一个休息服务,我们想要使用OAauth 2进行授权。 current draft(5月19日的v2-16)描述了four grant types。它们是用于获得授权的机制或流程(访问令牌)。

  1. 授权码
  2. 隐含授权
  3. 资源所有者凭据
  4. 客户端凭据
  5. 似乎我们需要支持所有这四个,因为它们用于不同的目的。前两个(可能是最后一个)可以从需要访问API的第三方应用程序中使用。授权代码是授权足够幸运地驻留在安全服务器上的Web应用程序的标准方法,而隐式授权流程将是客户端应用程序的选择,该客户端应用程序无法完全保密其凭据(例如,移动/桌面)应用程序,JavaScript客户端等) 我们希望自己使用第三种机制在移动设备上提供更好的用户体验 - 而不是将用户带到Web浏览器等的登录对话框,用户只需在应用程序中直接输入他或她的用户名和密码并登录。 我们还希望使用客户端凭据授予类型来获取可用于查看与任何用户无关的公共数据的访问令牌。在这种情况下,这不是授权,而是类似于API密钥,我们使用它来仅访问已向我们注册的应用程序,如果需要,我们可以选择撤销访问权限。

    所以我的问题是:

    1. 您认为我是否正确理解了不同授权类型的目的?
    2. 您如何保密客户凭据?在第三和第四种情况下,我们需要在客户端的某个地方拥有客户端ID和客户端秘密,这听起来不是一个好主意。
    3. 即使您使用隐式授权类型并且您没有公开您的客户端机密,是什么阻止其他应用程序使用相同的授权机制和您的客户端ID模拟您的应用程序?
    4. 总而言之,我们希望能够使用客户端应用程序的客户端凭据和资源所有者凭据流。这两种流程都要求您以某种方式存储客户端密钥,但客户端是移动或JavaScript应用程序,因此很容易被盗。

1 个答案:

答案 0 :(得分:55)

我面临着类似的问题,而且对OAuth来说也相对较新。我已经在我们的API中实现了“资源所有者密码凭证”,供我们的官方移动应用程序使用 - 网络流程似乎在移动平台上使用时非常糟糕,一旦用户安装应用程序并信任这是我们的官方应用程序,他们应该很乐意直接在应用程序中输入用户名/密码。

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

只需在每个要点上找到答案:

  1. 我一直在重新阅读规范的不同草稿,看看是否有任何改变,我主要关注资源所有者密码凭据部分,但我认为你对这些是正确的。客户端凭证(4)我认为内部或第三方服务也可能需要访问不仅仅是“公共”信息,例如,您可能需要分析或需要获取所有用户信息的内容。

  2. 我认为您不能对客户保密。

  3. 没有什么可以阻止其他人使用您的客户端ID。这也是我的问题。一旦您的代码离开服务器并且作为应用程序安装或在浏览器中作为Javascript运行,您就不能假设任何秘密。

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

    似乎您的客户端凭据的用例不同,因为您正在谈论第三方应用,并且只通过此方法提供公共数据。我认为您的担忧是有效的(任何人都可以窃取并使用其他人的API密钥),但如果您只需要免费注册即可获得API密钥,我不明白为什么有人真的想偷一个。

    您可以监控/分析每个API密钥的使用情况,以尝试检测滥用行为,此时您可以使一个API密钥无效并为合法用户提供新密钥。这可能是最好的选择,但它绝不是安全的。

    如果你想把它锁得更紧,你也可以使用类似刷新令牌的方案,虽然我不知道你真正获得了多少。如果你每天一次过期暴露于Javascript的api令牌,并要求第三方使用(秘密)刷新令牌进行某种服务器端刷新,那么偷来的api令牌永远不会超过一天。可能会鼓励潜在的令牌小偷改为注册。但对其他人来说却是一种痛苦,所以不确定这是否值得。