如何在使用 OAuth2 的资源所有者密码凭据授予类型时对客户端凭据保密 [英] How to keep the client credentials confidential, while using OAuth2's Resource Owner Password Credentials grant type

查看:42
本文介绍了如何在使用 OAuth2 的资源所有者密码凭据授予类型时对客户端凭据保密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在构建一个休息服务,我们想使用 OAauth 2 进行授权.当前草案(5 月 19 日的 v2-16)描述了四种资助类型.它们是获取授权(访问令牌)的机制或流程.

We are building a rest service and we want to use OAauth 2 for authorization. The current draft (v2-16 from May 19th) describes four grant types. They are mechanisms or flows for obtaining authorization (an access token).

  1. 授权码
  2. 隐性授权
  3. 资源所有者凭据
  4. 客户凭据

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

It seems we need to support all four of them, since they serve different purposes. The first two (and possibly the last one) can be used from third-party apps that need access to the API. The authorization code is the standard way to authorize a web application that is lucky enough to reside on a secure server, while the implicit grant flow would be the choice for a client application that can’t quite keep its credentials confidential (e.g. mobile/desktop application, JavaScript client, etc.).
We want to use the third mechanism ourselves to provide a better user experience on mobile devices – instead of taking the user to a login dialog in a web browser and so on, the user will simply enter his or her username and password directly in the application and login. We also want to use the Client Credentials grant type to obtain an access token that can be used to view public data, not associated with any user. In this case this is not so much authorization, but rather something similar to an API key that we use to give access only to applications that have registered with us, giving us an option to revoke access if needed.

所以我的问题是:

  1. 您认为我是否正确理解了不同资助类型的目的?
  2. 您如何对您的客户凭据保密?在第三种和第四种情况下,我们都需要在客户端的某个地方拥有客户端 ID 和客户端机密,这听起来不是一个好主意.
  3. 即使您使用隐式授权类型并且不公开您的客户端密钥,什么阻止另一个应用程序使用相同的授权机制和您的客户端 ID 来冒充您的应用程序?

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

To summarize, we want to be able to use the client credentials and resource owner credentials flow from a client application. Both of these flows require you to store the client secret somehow, but the client is a mobile or JavaScript application, so these could easily be stolen.

推荐答案

我面临着类似的问题,而且我也是 OAuth 的新手.我已经在我们的 API 中实现了资源所有者密码凭据",供我们的官方移动应用程序使用——网络流似乎在移动平台上使用起来非常糟糕,一旦用户安装了应用程序并信任这是我们的官方应用程序,他们应该会很舒服地直接在应用程序中输入用户名/密码.

I'm facing similar issues, and am also relatively new to OAuth. I've implemented "Resource Owner Password Credentials" in our API for our official mobile app to use -- the web flows just seem like they'd be so horrible to use on a mobile platform, and once the user installs an app and trusts that it's our official app, they should feel comfortable typing username/password directly into the app.

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

The problem is, as you point out, there is no way for my API server to securely verify the client_id of the app. If I include a client_secret in the app code/package, then it's exposed to anyone who installs the app, so requiring a client_secret wouldn't make the process any more secure. So basically, any other app can impersonate my app by copying the client_id.

只是直接回答你的每一点:

Just to direct answers at each of your points:

  1. 我不断重新阅读规范的不同草案,看看是否有任何变化,并且主要关注资源所有者密码凭据部分,但我认为您对这些是正确的.Client Credentials(4) 我认为也可以由内部或第三方服务使用,这些服务可能需要访问的不仅仅是公共"信息,比如您可能有分析或需要获取所有用户信息的东西.

  1. I keep re-reading different drafts of the spec to see if anything's changed, and am focused mostly on the Resource Owner Password Credentials section, but I think you're correct on these. Client Credentials(4) I think could also be used by an in-house or third-party service that might need access to more than just "public" information, like maybe you have analytics or something that need to get information across all users.

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

I don't think you can keep anything confidential on the client.

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

Nothing stops someone else from using your client id. This is my issue too. Once your code leaves the server and is either installed as an app or is running as Javascript in a browser, you can't assume anything is secret.

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

For our website, we had a similar issue to what you describe with the Client Credentials flow. What I ended up doing is moving the authentication to the server side. The user can authenticate using our web app, but the OAuth token to our API is stored on the server side, and associated with the user's web session. All API requests that the Javascript code makes are actually AJAX calls to the web server. So the browser isn't directly authenticated with the API, but instead has an authenticated web session.

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

It seems like your use-case for Client Credentials is different, in that you're talking about third-party apps, and are only serving public data through this method. I think your concerns are valid (anyone can steal and use anyone else's API key), but if you only require a free registration to get an API key, I don't see why anyone would really want to steal one.

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

You could monitor/analyze the usage of each API key to try to detect abuse, at which point you could invalidate one API key and give the legitimate user a new one. This might be the best option, but it's in no way secure.

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

You could also use a Refresh Token-like scheme for this if you wanted to lock it up a bit tighter, although I don't know how much you would really gain. If you expired the Javascript-exposed api tokens once a day and required the third-party to do some sort of server-side refresh using a (secret) refresh token, then stolen api tokens would never be good for more than a day. Might encourage potential token thieves to just register instead. But sort of a pain for everyone else, so not sure if this is worth it.

这篇关于如何在使用 OAuth2 的资源所有者密码凭据授予类型时对客户端凭据保密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆