存储密码以登录第三方API

时间:2016-10-17 00:06:15

标签: javascript node.js security express

我正在使用Node& amp;编写交易应用程序。表示后端。每个用户都有自己的应用程序登录,但为了使其有用,应用程序还需要登录用户的经纪帐户。

有问题的经纪帐户有一个REST API,您可以在其中POST该系统的登录名和密码。该API不提供SSO或OAuth作为身份验证选项。验证的唯一方法是POST uid和密码。

因此,此处涉及两个登录:一个登录到我的应用程序,另一个完全单独登录到经纪帐户。每个登录都使用不同的用户ID和密码。

我遇到的问题是弄清楚如何存储经纪帐户的密码。我知道存储密码是一个坏主意。但是,如果我存储的所有内容都是经纪人密码的咸味哈希,我将无法将其反转并获得实际密码。因此,我的应用程序无法登录经纪帐户,除非用户再次输入该密码。

(顺便说一句,还有另一个程序可以执行此操作。https://dough.com要求用户登录面团,然后您还必须登录TD Ameritrade。登录两次是我所做的。我希望避免。)

是否有合理且安全的方法来存储此第三方API的密码,以便我的应用可以代表用户登录,而不必强迫用户每次使用我的应用时都提交密码?我知道这里存在很大的安全风险。如果答案是否定的,那么我就赢了。

2 个答案:

答案 0 :(得分:4)

编辑&强制性 - 实际上解决方案是不要这样做。虽然技术上可行,但几乎肯定无法正确实施。将泄露用户的密码。

是的,但这并不容易实施是关键。 JavaScript OpenPGPJS library就是你想要的。

为了获得稍微安全的系统,不允许您的后端解密密码。这就是JS库的用武之地,它通过浏览器提供PGP加密。

您可以将PGP密码从用户密码中删除,或者让它们为解密提供新密码。或者,您可以为密码加密生成随机密钥,然后创建一个可以访问随机密钥的主密钥 - 使用用户输入加密主密钥。

无论您使用哪种方法,都需要让他们输入密码才能在需要时解密记录,或者将密码添加到本地会话中。前者是安全的,后者具有明显的安全隐患。

使用示例提供的密码进行简单字符串加密:

var options, encrypted;

options = {
    data: 'Hello, World!',      // input as String
    passwords: ['secret stuff'] // multiple passwords possible
};

openpgp.encrypt(options).then(function(ciphertext) {
    encrypted = ciphertext.data; // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
});

解密:

options = {
    message: openpgp.message.readArmored(encrypted), // parse armored message
    password: 'secret stuff'                         // decrypt with password
};

openpgp.decrypt(options).then(function(plaintext) {
    return plaintext.data; // 'Hello, World!'
});

答案 1 :(得分:1)

我认为你有几个选择,你选择的决定应该取决于你想要承担的风险。 如果是您所暗示的财务数据,我认为该决定显然应该没有做到这一点。

一种选择是使用从用户的本地密码派生的密钥存储在服务器上加密的第三方API密码。由于您没有存储用户的本地密码,因此当您拥有本地密码时,您只能在用户登录时解密第三方API密码,如果您希望将来调用模拟用户的API,您将拥有该密码。将第三方密码的纯文本版本保留在服务器内存中(用户的会话)。我认为,虽然在某些应用程序中这可能是一个可行的选择,但对于财务数据而言,这是不可接受的。

你可以做的另一件事是加密Javascript中的第三方API密码,正如Dave Lasley在他的回答中所描述的那样。虽然这可行,但它增加了很多复杂性,正如他也指出的那样,实施将是关键。在没有引入漏洞的情况下,很难做到这一点并保持一段时间。另外Javascript加密有问题,最好的做法是不要在Javascript中进行加密。您必须在Javascript内存中保留第三方API密码,这是一个非常弱的控件,任何单个XSS都可以从那里窃取它(任何其他浏览器存储甚至比内存中的Javascript对象更糟糕)。此外,第三方API需要支持您域中的CORS(或*显然)。

我的看法是,实现这一目标的唯一好方法是使用OAuth2仔细实施。如果API不支持,那么不幸的是你不应该这样做。