如何在使用OAuth2的资源所有者密码凭据授权types时保持客户端凭据的机密性
我们正在build立一个rest服务,我们希望使用OAuth 2进行授权。 目前的草案 (5月19日第2版)描述了四种授权types 。 它们是获得授权的机制或stream程(访问令牌)。
- 授权码
- 隐含的授予
- 资源所有者证书
- 客户端凭证
看来我们需要支持他们四个,因为他们有不同的目的。 前两个(也可能是最后一个)可以从需要访问该API的第三方应用程序使用。 授权代码是授权一个足够幸运地驻留在安全服务器上的Web应用程序的标准方式,而隐式授权stream程将成为客户端应用程序的select,而客户端应用程序不能完全保留其凭据的机密性(例如,移动/桌面应用程序,JavaScript客户端等)。
我们希望使用第三种机制来在移动设备上提供更好的用户体验 – 而不是让用户在Web浏览器中login对话框等,用户只需直接在应用程序中input用户名和密码并login。 我们还希望使用“客户端凭据”授予types来获取可用于查看公用数据的访问令牌,而不与任何用户关联。 在这种情况下,这不是太多的授权,而是类似于API密钥的东西,我们只使用它来访问已经注册的应用程序,如果需要,我们可以select撤销访问。
所以我的问题是:
- 你是否认为我正确理解了不同授权types的用途?
- 你如何保持你的客户端的资料保密? 在第三种情况和第四种情况下,我们都需要在客户端的某处设置客户端ID和客户端密码,这听起来不是一个好主意。
- 即使使用隐式授权types,并且不公开您的客户端密码,也会阻止其他应用程序使用相同的授权机制和客户端ID来模拟您的应用程序?
总而言之,我们希望能够使用来自客户端应用程序的客户端证书和资源所有者证书stream。 这两种stream程都要求您以某种方式存储客户端密钥,但客户端是移动设备或JavaScript应用程序,因此这些可能很容易被盗用。
我面临类似的问题,也是OAuth相对较新的。 我们在我们的官方移动应用程序的API中实现了“资源所有者密码凭证” – networkingstream量在移动平台上看起来像是太可怕了,一旦用户安装了应用程序并相信这是我们的官方应用程序,他们应该感觉舒适直接input用户名/密码到应用程序。
问题是,正如你指出的,我的API服务器无法安全地validation应用程序的client_id。 如果我在应用程序代码/包中包含client_secret,那么它将暴露给安装该应用程序的任何人,因此要求client_secret不会使该过程更安全。 所以基本上,任何其他的应用程序可以通过复制client_id来模拟我的应用程序。
只是为了直接回答你的每一点:
-
我不断重新阅读规范的不同草案,看是否有任何改变,主要集中在资源所有者密码凭据部分,但我认为你是正确的。 客户端凭证(4)我认为也可以被内部或第三方服务使用,这些服务可能不仅需要访问“公共”信息,例如可能有分析或需要在所有用户中获取信息的内容。
-
我不认为你可以保留任何保密的客户端。
-
没有什么能阻止别人使用你的客户端ID。 这也是我的问题。 一旦你的代码离开服务器,并作为一个应用程序安装或作为JavaScript在浏览器中运行,你不能假设任何事情是秘密的。
对于我们的网站,我们遇到了与您使用客户端证书stream程所描述的类似的问题。 我最终做的是将身份validation移到服务器端。 用户可以使用我们的networking应用程序进行身份validation,但是我们API的OAuth令牌存储在服务器端,并且与用户的networking会话相关联。 Javascript代码所做的所有API请求实际上是对Web服务器的AJAX调用。 因此,浏览器不是直接通过API进行身份validation,而是具有经过身份validation的Web会话。
对于Client Credentials而言,您的用例似乎不同,因为您正在讨论第三方应用程序,并且仅通过此方法提供公共数据。 我认为你的担心是有效的(任何人都可以窃取和使用任何其他的API密钥),但是如果你只需要免费注册来获得API密钥,我不明白为什么有人会真的想偷一个。
您可以监控/分析每个API密钥的使用情况,以尝试检测滥用情况,此时您可以使一个API密钥无效,并为合法用户提供一个新密钥。 这可能是最好的select,但它是不可靠的。
如果你想把它锁得更紧一点,你也可以使用一个类似Refresh Token的scheme,尽pipe我不知道你会获得多less收益。 如果您每天一次过期使用Javascript暴露的api令牌,并要求第三方使用(秘密)刷新令牌进行某种服务器端刷新,那么被盗的api令牌永远不会超过一天。 可能鼓励潜在的令牌盗贼只要注册。 但是对于其他人来说也是一种痛苦,所以不确定这是否值得。