javascript - OAuth : How to hide API Secret Key from javascript

标签 javascript oauth-2.0 aes

我们正在迁移基于 MVC 的服务器应用程序并制作一个 REST-ful API,通过它处理调用。

我一直在阅读 AES 加密和 OAuth2,并决定实现一个从这些概念中成长起来的解决方案,如下所示:

  1. 客户端发送请求以提供用户 ID 或电子邮件登录。此请求是使用 API key 的 HMAC。
  2. 服务器检查用户 ID/电子邮件是否与现有帐户匹配,如果找到,则创建并存储一个服务器随机数,将其作为响应的一部分发送给客户端。
  3. 客户端创建自己的客户端随机数,并根据 API key 和两个随机数创建一个新的临时 key 。然后它会发送一个登录请求,其中包含使用此临时 key 加密的密码 [以增加熵并避免以明文形式发送密码]。
  4. 服务器使用它在这个平台上为此客户端存储的最新随机数 [移动和网络客户端可以有自己不同的随机数和 session ] 和以明文发送的客户端随机数解密密码和 HMAC,如果 HMAC check out 它,则根据数据库 [PBKDF2 哈希和加盐] 验证密码。
  5. 如果请求有效且密码和用户 ID 匹配记录,则在该平台上为该用户 ID 创建一个新的 session key ,并将此 key 发送到客户端,并将用于 HMAC 来自客户端的每个 API 请求今后。
  6. 任何新的非登录请求都将包含根据 session key 和随机 IV 计算得出的 HMAC 签名。

所有通信都通过 TLS 处理,因此这是增加的安全性,而不是唯一的防线。

在移动应用程序上,这会起作用,因为您可以将移动应用程序的 key 隐藏在配置文件中,这提供了一些不错的安全措施 - [也许不是很多我不完全确定]但是如果我们尝试转换从我们的网页到此表单的所有请求这意味着使用 Javascript 来处理客户端 AES 加密和身份验证以及... well as this article clearly explains ,“如果您将 API key 存储在 JavaScript 网络应用程序中,您还不如在主页上以粗体字打印出来,因为现在全世界都可以通过浏览器的开发工具访问它。”

我可以只使用随机数作为 API key ——或者完全放弃对这些请求使用 AES 加密,并尝试通过其他方式(例如 CSRF token )进行验证,并确保所有请求都来 self 们自己的前端方式 - 但如果我们想创建一个允许与其他页面或服务集成的 API,那么这将行不通,即便如此,我将如何保护客户端的 secret session key ?

该文章建议生成一次性 cookie 作为 token ,但这是一种有限的解决方案,适用于发布者的服务,但不适用于我们。我希望 HMAC 能够对用户发送的每个请求使用用户特定的 key 进行处理,该 key 可以过期并重置,并且由于该服务最终会处理资金,所以我希望请求身份验证被严格锁定。

那么我的选择是什么?

我是否只是放弃 Javascript 因为它 is doomed ?有什么方法可以存储 key ,而不会像硬编码到 .js 脚本中那样将其公开?我是否应该生成一个新的临时 key 仅用于登录调用并在用户请求服务器随机数时将其发送给用户?

此外,我首先链接到的帖子建议使用 cookie 为客户端存储 session key ,然后从 JS 访问该 key 。这样可以吗,还是会提供比密封更多的孔?

最佳答案

很高兴知道哪些措施可以防止哪些安全漏洞。

您说得对,JavaScript 不适合加密,因为没有地方可以存储 secret 。也没有好的加密库,因为您不应该在 JavaScript 中进行加密。

session key 可以作为身份验证 key 。如果您使用的是 TLS,您的连接是安全的,攻击者无法知道 session key 。 此外,JavaScript 不需要知道 session key 。默认情况下,每次请求都会发送 Cookie。您可以将 cookie 设置为仅限 http 的 cookie。您不必这样做,但它确实增加了另一层安全性。

您可以给 session cookie 一个很长的过期时间,这样它基本上就像一个 secret 的 API key 一样工作。浏览器将负责安全地存储 cookie。建议经常轮换 session key ,通常是在每个新 session 开始时和身份验证信息更改时(如密码重置)。

CSRF token 可防止重放攻击。绝对建议使用 CSRF token 保护修改请求。您不需要对每个请求进行 CSRF 检查,只需请求修改敏感信息(例如您的登录凭据,或者在您的情况下:交易)。 对于 CSRF token ,您可以使用与 session key 相同的方法:将其存储在 cookie 中。

关键部分是 JavaScript 不需要知道这些。

我相信您也意识到了一件重要的事情,即您生成的任何 key 或随机数都必须是加密安全的。不要使用低熵函数。

所以:

  1. 您不需要加密用户 ID 或电子邮件,TLS 已经为您完成了。此外,您也可以发送密码,不需要在第 3 步中单独发送。我们不会在 JavaScript 中进行任何加密。所有加密均由 TLS/HTTPS 单独处理。

  2. 如果您有单独的身份验证服务器(如单点登录),则此方法很好。否则你可以跳过这一步。

  3. 你不需要这个。

  4. 服务器不需要解密任何东西,加密由 TLS 处理。如何存储密码本身就是一个话题,但我想您已经知道了。

  5. 好的。同样,客户端不应加密任何内容。

  6. 仅发送 session key 。够了。

修改为:

  1. 客户端发送登录凭据。连接必须安全。

  2. 服务器验证凭据并将身份验证 token 作为 cookie 发送,并通过 session 列表跟踪身份验证 token 。

对于每个请求:

  • 客户端包含身份验证 token 。如果您使用 cookie,这会自动发生。

  • 服务器验证身份验证 token 并可能生成一个新的 token 供客户端使用。

关于javascript - OAuth : How to hide API Secret Key from javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38513498/

相关文章:

javascript - 具有相同名称和不同 id 的选择字段数组。

javascript - javascript中使用prompt()方法初始化变量时,初始化变量的类型是什么?

mysql - Play Framework 2.5 - scala oauth2 提供程序问题

android - 如何在推特中使用仅限应用程序的oauth?

python - 易于使用的 Python 加密库/包装器?

c - c 和 java 中的输出 AES/ECB/PKCS7 不相同

Javascript token 转换

javascript - Twitter bootstrap 工具提示显示在模态后面

php - 使用 Youtube Api v3 和 oauth2 无需用户身份验证即可将视频上传到我的 Youtube channel

Node.js 加密 : Invalid IV length