[英]How to keep the client credentials confidential, while using OAuth2's Resource Owner Password Credentials grant type
We are building a rest service and we want to use OAauth 2 for authorization.我们正在构建 rest 服务,我们希望使用 OAauth 2 进行授权。 The current draft (v2-16 from May 19th) describes four grant types .
当前的草案(5 月 19 日的 v2-16)描述了四种资助类型。 They are mechanisms or flows for obtaining authorization (an access token).
它们是获取授权(访问令牌)的机制或流程。
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.
前两个(也可能是最后一个)可以从需要访问 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 (eg mobile/desktop application, JavaScript client, etc.).
授权代码是授权 web 应用程序的标准方法,该应用程序幸运地驻留在安全服务器上,而隐式授权流将是不能完全保密其凭据的客户端应用程序的选择(例如移动/桌面应用程序,JavaScript 客户端等)。
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.我们希望自己使用第三种机制来在移动设备上提供更好的用户体验——而不是将用户带到 web 浏览器等中的登录对话框,用户只需直接在应用程序中输入他或她的用户名和密码并登录。 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.
我们还想使用 Client Credentials 授权类型来获取可用于查看公共数据的访问令牌,不与任何用户关联。 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.
在这种情况下,这不是太多的授权,而是类似于 API 密钥的东西,我们使用该密钥仅授予已向我们注册的应用程序的访问权限,从而使我们可以在需要时撤销访问权限。
So my questions are:所以我的问题是:
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.
这两个流程都需要您以某种方式存储客户端密码,但客户端是移动应用程序或 JavaScript 应用程序,因此很容易被窃取。
I'm facing similar issues, and am also relatively new to OAuth.我面临着类似的问题,而且对 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 中实现了“资源所有者密码凭据”,供我们的官方移动应用程序使用——web 流看起来就像它们在移动平台上使用起来太可怕了,一旦用户安装了应用程序并信任这是我们的官方应用程序,他们应该觉得直接在应用程序中输入用户名/密码很舒服。
The problem is, as you point out, there is no way for my API server to securely verify the client_id of the app.问题是,正如您所指出的,我的 API 服务器无法安全地验证应用程序的 client_id。 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.
如果我在应用程序代码/包中包含 client_secret,那么它会暴露给任何安装该应用程序的人,因此要求 client_secret 不会使该过程更加安全。 So basically, any other app can impersonate my app by copying the client_id.
所以基本上,任何其他应用程序都可以通过复制 client_id 来模拟我的应用程序。
Just to direct answers at each of your points:只是为了直接回答你的每一点:
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.
Client Credentials(4) 我认为也可以由内部或第三方服务使用,这些服务可能需要访问的不仅仅是“公共”信息,比如您可能有分析或需要获取所有用户信息的东西。
I don't think you can keep anything confidential on the client.我认为你不能对客户保密。
Nothing stops someone else from using your client id.没有什么能阻止其他人使用您的客户 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.
一旦您的代码离开服务器并作为应用程序安装或在浏览器中作为 Javascript 运行,您就不能假设任何事情都是秘密的。
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.
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.
所有 API 请求 Javascript 代码实际上都是对 Z2567A5EC9705EB7AC2C984033E06 服务器的 AJAX 调用。 So the browser isn't directly authenticated with the API, but instead has an authenticated web session.
所以浏览器没有直接使用 API 进行身份验证,而是有一个经过身份验证的 web session。
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.您可以监控/分析每个 API 密钥的使用情况以尝试检测滥用情况,此时您可以使一个 API 密钥无效并为合法用户提供一个新密钥。 This might be the best option, but it's in no way secure.
这可能是最好的选择,但它绝不安全。
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.如果您想将其锁定得更紧,您也可以为此使用类似 Refresh Token 的方案,尽管我不知道您会真正获得多少。 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.
如果您每天使 Javascript 公开的 api 令牌过期一次,并要求第三方使用(秘密)刷新令牌进行某种服务器端刷新,那么被盗的 api 令牌将永远不会超过一天。 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.
但对其他人来说有点痛苦,所以不确定这是否值得。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.