客户端 ID 和机密
Posted
技术标签:
【中文标题】客户端 ID 和机密【英文标题】:Client IDs and secrets 【发布时间】:2018-06-27 18:58:06 【问题描述】:Request URL:
POST https://example.com/oauth/token
Request Headers:
Content-Type: application/x-www-form-urlencoded
Request POST Body:
grant_type=password&username=joebloggs&
password=password1234&client_id=myclient&client_secret=myclientsecret
Response:
"access_token": "omitted for brevity",
"token_type": "bearer",
"expires_in": 1200,
"refresh_token": "b3cc9c66b86340c5b743f2a7cec9d2f1"
我想使用从单页应用发送的 JWT 来保护我的 Umbraco Web api 端点。我发现this lib 可以满足我的大部分需求。
由于我使用了InMemoryOAuthClientStore
,因此文档声明必须在身份验证请求中提供客户端 ID 和密码(我假设这用于匹配商店中的 OAuthClient
?):
client_id = 有效的客户端 ID(仅在配置了客户端存储时才需要)
client_secret = 有效的客户端密码(仅在配置了客户端存储且客户端“安全”时才需要)
我想知道它们的用途。如果我使用来自客户端的 AJAX 调用对https://example.com/oauth/token
进行此授权调用,我需要在客户端存储 id 和 secret。我的直觉告诉我,这不是它的预期用途。
另一方面,在这种情况下,客户端 ID 和密码都伴随着用户凭据,因此如果没有有效的用户名和密码,它们就毫无价值。
请有人对此有所了解。
【问题讨论】:
【参考方案1】:使用用户名和密码请求令牌,然后将该令牌存储在请求端有两个主要原因。
-
额外的安全性。用户名/密码组合不会随每个发送
请求,但仅每 1200 秒/分钟一次。
处理请求的服务器只需要检查
令牌而不是性能繁重的密码哈希
请求。
还有其他原因,请看下面的链接。
https://stormpath.com/blog/token-authentication-scalable-user-mgmthttps://www.w3.org/2001/sw/Europe/events/foaf-galway/papers/fp/token_based_authentication/
https://security.stackexchange.com/questions/63435/why-use-an-authentication-token-instead-of-the-username-password-per-request
https://security.stackexchange.com/questions/151770/token-based-api-security-over-repeated-username-password-requests What is token based authentication?更新
client_id 是应用程序的公共标识符。 client_secret 是只有应用程序和授权服务器知道的秘密。以下链接中的更多信息。
https://security.stackexchange.com/questions/76351/whats-the-point-of-the-client-secret-in-oauth2-if-it-doesnt-need-to-be-used
https://salesforce.stackexchange.com/questions/14009/whats-the-benefit-of-the-client-secret-in-oauth2
https://www.oauth.com/oauth2-servers/client-registration/client-id-secret/
【讨论】:
我要求澄清有关客户端 ID 和机密以及应如何使用它们的一些说明 - 而不是一般的令牌 更新了我的答案。 谢谢。您能否详细说明“安全客户端”?据我所知,没有这样的东西......(“仅当配置了客户端存储,并且客户端是“安全”时才需要”)【参考方案2】:有些客户端能够将某些信息(客户端机密)保密,而有些则不能。例如,如果您通过 ajax 直接从 javascript 向 oauth 端点发出请求 - 此客户端不是“安全的”。它不能私下存储客户端机密,因为任何人都可以直接在 javascript 代码中或通过在浏览器开发工具中观察请求来查看此机密。对于此类客户端(移动应用程序是另一个示例),在任何流程(包括“密码”流程)中使用客户端密码都没有任何意义。
“安全”客户端的示例是您拥有的 Web 服务器。因此,您不会直接从 javascript 向 oauth 端点发出请求,而是将凭据发送到您的服务器,然后服务器向 oauth 端点发出请求。从某种意义上说,该客户端是“安全的”,它能够私下存储客户端机密。对于这样的客户,要求客户机密确实有意义(甚至我会说是要求)。
总之,你的直觉是正确的——你不应该在你的情况下使用客户端密码,因为它没有任何用处。
现在,即使您不使用客户端密码,您仍然可以单独使用 client_id。例如,您可能会为不同的客户发出一组不同的索赔。请注意,客户端 ID 是公共信息,因此您不应仅根据 client_id 做出任何敏感决定 - 它不能被信任。
另请注意,“密码”流程是最后的手段,只能由您拥有的客户使用,并且在没有其他流程可用时使用。
【讨论】:
感谢您的解释。我想这归结为图书馆的限制,因为正如你所说,我不需要秘密,但我需要使用它,因为我想使用InMemoryOAuthClientStore
。
@Johan 也许您可以更详细地描述您的情况。据我了解 - 您只有一个客户端,即您自己的单页 Web 应用程序。
对。从长远来看,我的客户也希望能够从外部系统生成令牌。我的想法是在我们的应用程序之间使用一个共同的秘密来生成令牌。为了能够在这个库中定义一个令牌秘密,我必须在一个客户端中定义它,它被传递给InMemoryOAuthClientStore
。但是,将令牌创建保留在我的应用程序上,并让他们通过我的 API 生成令牌,使用 API 密钥、基本身份验证或类似的东西来保护它,也许这是一个更好的解决方案?
@Johan 我对 Umbarco 知之甚少(实际上一无所知),但这个库似乎允许您定义不安全的客户端(OAuthClient 具有 SecurityLevel 属性),不应该要求客户端机密经过。因此,您可以将一个客户端用于您的应用程序(不安全),将另一个客户端用于您的客户(安全)。但请注意,您不应为第三方客户端(例如您的客户应用程序)使用“密码”流程,因为您不应将用户密码泄露给第三方。
对。非常感谢您抽出宝贵的时间,我已经找到了我现在正在寻找的答案 :) 显然不能再给您 3 个小时的赏金以上是关于客户端 ID 和机密的主要内容,如果未能解决你的问题,请参考以下文章
Google Oauth 错误:应设置至少一个客户端机密(已安装或 Web)
为啥机密和公共客户端需要应用程序来处理 spring/keycloak 适配器中的会话?