安全存储访问令牌的最佳实践

信息安全 加密 休息 Facebook 用户管理
2021-09-04 13:22:26

为您的用户存储另一个 api 的访问令牌的最佳实践是什么?特别是,我正在与一些朋友一起开发一个应用程序,让用户登录 Facebook 以验证我们的内部 REST api 并使其能够获取他们的朋友(和其他东西)。

我正在考虑生成一个密钥并使用它来加密用户 Facebook 帐户的长期访问令牌以及可能的其他敏感信息。作为加密方案,我将使用 AES-256-CBC 并将密钥发送给客户端,客户端会保留它(并偶尔刷新一次)。但是,如果我生成具有任何随机性的密钥,那么用户只能使用一个客户端。因为其他客户端需要该密钥来解密 Facebook 访问令牌和其他数据。一个解决方案是在 Facebook 登录期间从独特的东西生成密钥,但不幸的是,我能找到的唯一这样的东西是用户 ID,我需要在数据库中找到用户的记录。

在stackoverflow上实际上有很多关于这个的话题,但没有什么能回答我想要的。我真正想要的是使用只有客户端知道的密钥来加密 Facebook 访问令牌和其他数据。只有当用户使用 Facebook sdk 进行身份验证或提供当前密钥时,才能创建这些密钥。

有任何想法吗?

3个回答

客户端存储的内容和服务器存储的内容之和必须足以恢复用户特定的秘密数据(例如 Facebook 访问令牌)。客户端存储的主要是用户的密码(客户端唯一永久存储的区域是用户的大脑,如果我们想让用户随意使用几台不同的机器)。如果我理解正确,您不希望您的服务器“按原样”存储数据:如果您的服务器完全受到威胁,用户的秘密应该仍然是安全的(尽可能)。

这指向基于密码的加密从用户的密码导出一个对称密钥K,用于对称加密包含用户秘密的包,例如 Facebook 帐户。从技术上讲,这看起来像这样:

  • 当用户注册时,他选择他的密码P并将其发送到您的服务器。
  • 您的服务器生成一个随机盐值S并在PS上计算PBKDF2,以产生 256 位的输出T我们将A称为T的前 128 位,将K称为另一 128 位的一半。
  • 前半部分(A)存储在服务器的数据库中;这将用于对用户进行身份验证。
  • 后半部分(K存储;这是该用户的对称密钥。用户的秘密将使用K加密。
  • 当用户登录时,他将他的姓名和P发送到您的服务器(通过 HTTPS)。您的服务器检索该用户的盐S(存储在其数据库中)并重新计算T(将PS与 PBKDF2 一起使用)。如果重新计算的T的前半部分与存储的 A匹配,则用户通过身份验证, T后半部分K。然后,服务器可以解密存储的捆绑包并访问 Facebook 访问令牌。

使用此设置,服务器永远不会存储(在其磁盘或数据库中)明文 Facebook 访问令牌,但它可以在用户登录时访问它;只要需要,服务器就可以记住(在 RAM 中)Facebook 访问令牌。

请注意,当用户更改密码时,这也会更改K(服务器必须也生成一个新的 salt S,但即使服务器错误地没有,K仍然会更改);因此,服务器必须用旧的K解密存储的包,并在更改密码时用新的K再次加密。这并不难集成,因为密码更改界面通常会要求输入旧密码新密码,因此服务器同时拥有两者。

另请注意,忘记密码时,捆绑包将丢失。这种情况无法恢复。如果用户忘记了自己的密码,那么您将不得不进行一些密码重置,这类似于重新注册;并且必须获得一个新的 Facebook 访问令牌。


在上述所有内容中,我们看到您的服务器仍然可以看到用户的密码。如果您的服务器完全被入侵和劫持,那么攻击者将能够在攻击者控制服务器时观察所有登录用户的用户密码和用户的 Facebook 访问令牌。防止这种情况要困难得多。可以说,如果您的服务器仅提供一个 Web 界面,其中客户端的所有“智能”都是您的服务器发送的 Javascript,那么在这种情况下,不可能比上述方案做得更好。

Facebook Docs: Securing Graph API Requests提供了一个简单的解决方案。

上周我在第10 届 ISC 安全和密码学会议上看到有人提出了一种使用神经网络存储用户通行证的方法他创建了一个学习用户通行令牌并使用快速 NN 学习方法进行自我更新的 NN。这是一种新方法并保证安全,但需要在学习上多加注意。

更新

这篇论文的波斯语标题是在此处输入图像描述 它的意思User Access Control Using Neural Network and chaotic system

(堆栈不支持波斯语字符!我用图像代替!!!)