【问题标题】:Storing client secret on client side在客户端存储客户端机密
【发布时间】:2019-08-13 21:11:10
【问题描述】:

我正在使用名为 auth0 的外部服务来获取访问令牌并让我的用户使用我的 api。 Auth0 使用的是 Oauth2 协议。

简而言之,用户添加了用户名和密码,我正在使用 client_id(应用程序有一个 id)和 client_secret 调用 auth0,然后我得到一个 jwt 访问令牌作为回报。然后从那里我携带这个访问令牌来访问我自己的 api,因为我可以检查它的有效性。

我一直在寻找在客户端存储 client_id 和 client_secret 的安全性(例如 web (javascript)/mobile(本机或与 ionic 混合)),每个人都说它不安全,因为每个人都可以反转设计代码并获取 client_id 和 client_secret。好的...我可以接受...如果我没有凭据以获取访问令牌,我可以用它们做什么?

鉴于我不想存储 client_id 和 client_secret,我想到的一种解决方案是使用凭据直接调用我的 api (Java),然后我的 api 调用 auth0 并返回对应的访问令牌。这样,client_id 和 client_secret 就存储在后端,有人无法轻易获取它们。那安全吗?

但是我有一些端点,例如创建使用帐户,发送短信以进行电话验证等,不能有凭据。在这种情况下如何保护 api?如果我无法在客户端存储我自己的访问令牌,我如何获取访问令牌并在没有凭据的情况下访问我自己的 API?

谢谢

【问题讨论】:

  • 我看到 OAuth2 服务器接受没有client_secret 或空的请求。如果这不可能,也许您可​​以使用令牌流而不是代码流。
  • 嗨@mar​​tinstoeckli。你能给我任何链接吗?
  • 我成功地用这种方式访问​​了 Google-Drive 和 One-Drive,看看github.com/martinstoeckli/SilentNotes/blob/master/src/… [第 149 和 102 行]。 Google documentation中也有信息。

标签: authentication oauth-2.0 authorization


【解决方案1】:

OAuth 规范建议的一种可能解决方案是,您可以为您的应用程序使用三个不同的服务器。

客户端 后端服务器和额外的身份验证服务器。

这样做的首选方式是客户端将用户凭据发送到身份验证服务器。身份验证服务器将是包含客户端密码的后端服务器 身份验证服务器将对凭据进行身份验证并返回令牌。

然后客户端将使用从认证服务器获得的令牌来访问资源 API 服务器。

如果您想了解更多信息,请观看此视频 https://www.youtube.com/watch?v=rCkDE2me_qk

【讨论】:

  • 你好佐助。感谢您的答复。这就是我心中的想法。这回答了如何在客户端保护 clientid/secret。然而,这并不能回答我提到的其他两件事。首先,为什么在客户端存储 client_secret/id 是不安全的,因为为了获得访问令牌 (jwt),您需要只有用户知道的用户名/密码。另一件事是我如何保护不能有用户名/密码的 API,例如短信验证电话号码、注册、电子邮件验证等
  • 嗨@SymeonMattes,不建议在客户端存储client_secret/id,因为客户端的任何应用程序(扩展)都可能获取client_secret,获取它们不一定容易,但它最好的做法是不要将其存储在客户端。至于保护 API 的其他问题,您可以验证您在 API 服务器中随请求一起发送的令牌。您将在 API 端使用相同的客户端密码来验证令牌是否有效以及用户是否已通过身份验证
【解决方案2】:

在我看来,您几乎可以肯定使用了错误的 OAuth 流程。我将 Auth0 与 Ionic 一起用作 Web 应用程序和本机 Cordova 应用程序。我的客户端代码中根本没有客户端密码。

如果您遵循 Auth0 快速入门 (https://auth0.com/docs/quickstarts),如果您要部署到应用商店,则应该选择 (Native/Mobile App),如果您要部署 Ionic 的 Web 版本,则应选择 (Single-Page App)。从那里您可以选择 Cordova(用于原生)或 Angular(用于 SPA)。这些应该为您提供实施 OAuth 流程的说明,这些流程不需要您的客户端密码。我的猜测是您正在引用“常规 Web 应用程序”快速入门,它在服务器端运行并且可以安全地保存客户端机密。如果您使用的是 Ionic Hybrid/Native,那么这不是您正在编码的世界。

【讨论】:

  • 感谢您的回复。我知道这些事情。虽然我有登录页面应该驻留在客户端的规范。您/auth0 提到的内容如下:您在客户端上有一个链接,该链接将您重定向到 auth0 中的登录页面(好的,它可以是自定义的),您放置凭据,然后使用访问令牌将您重定向回应用程序为了访问您自己的自定义 API。这与我想要实现的用户体验相矛盾,但是,因为我知道我现在的方法并不安全,所以我正在寻找不同的替代方案。
  • 我明白了。在您的 OP 中,您没有提到您需要将登录表单保留在应用程序中(无需链接)。如果您的服务器端 API 为您进行身份验证,那么拥有您的 client_secret 就可以了。不过,这里有优点/缺点。您可能会通过执行不符合 OAuth 的实现来降低客户端的安全性(只需将用户/密码传递给您的 API)。使用 Auth0 的客户端库的好处是它们(希望)能够让您的客户端应用程序遵循原生和 SPA 的 OAuth 规范。因此,用户体验可能是应用内的首选,但这可能不太安全。
  • 好的...谢谢!我就是这么想的。我想确定这一点。
【解决方案3】:

我会考虑将对 Auth0 的调用包装到您自己的服务器端实现中,以确保安全。您的 API 获取用户凭据,然后调用 Auth0,这样您的 client_id/secret 在您的服务器上是安全的,并且可以在不损害您的安全性的情况下一直对客户端进行逆向工程。

关于其他无法获得凭据的 API,您非常不走运。它们的用例是由未经身份验证的第三方使用,因此至少不能真正保护帐户创建 API。但是,您仍然可以使用一些精心设计的约束来限制攻击面。例如。您可以要求使用电子邮件地址/电话号码进行注册,并且您不允许使用相同的地址/电话号码两次。如果您设置了您首先需要确认您的电子邮件地址才能验证您的电话号码的流程,这将使攻击者的生活变得更加困难。他需要一个真实有效的电子邮件地址,并且需要一些自动化来接收您的确认邮件,然后才能致电您的 SMS 服务。您还可以对每个 IP 地址的服务进行速率限制,这样攻击者就不会通过在短时间内发出大量 SMS 验证调用来导致您的 SMS 成本飙升。

【讨论】:

  • 您好 Jan。感谢您的回答...非常清楚!但是,我仍然不明白为什么在客户端存储 client_id/secret 是不安全的(好吧,有人得到它们......我不在乎),因为为了访问我的 api,他需要获得访问权限来自 auth0 的令牌。为了从那里获得访问权限,他需要 client_id/secret(存储在应用程序中)和只有他知道的用户名/密码。
  • 因为如果我正确阅读了 Auth0 的 API,您可以使用 client_id/secret 来获取管理 API 的访问令牌。使用管理 API,您可以获得所有用户的列表(包括电子邮件地址等)。这是等待发生的数据泄漏。你也可能造成其他各种破坏(只需检查 API auth0.com/docs/api/management/v2)。这就是为什么您不应该将此信息放在好奇的最终用户可以访问的任何地方。
猜你喜欢
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
  • 2018-04-25
  • 2019-05-29
  • 1970-01-01
  • 2018-06-27
  • 1970-01-01
  • 2021-07-15
相关资源
最近更新 更多