我正在努力寻找一种方法来安全地保存访问 token ,这是我的网络应用程序在用户授权应用程序后从 DiscordAPI 检索到的。
我正在为 Discord Bot 创建一个网络界面。这里很重要,不是每个人都可以使用它。只应允许特定 Discord 服务器上的服务器版主等访问网站的大部分内容。为此,我使用 Discord 中的 OAuth2 内容来检索访问 token ,通过它我可以获得用户信息,例如他们的唯一 ID。 然后,该 ID 用于检查他们在 Discord 服务器上的 Angular 色类型。
现在获取 Access-Token 的部分已经编写好了,看起来工作正常。我可以使用 token 从 Discord API 等查询数据。
我主要担心这里的安全问题。我已经阅读了几篇不同的帖子,但每个人似乎对此都有不同的看法。
我经常读到(甚至在 Auth2 网站上)的一个“解决方案”是将 token 保存在 cookie 中。
我不确定这是否安全。我不能简单地将 token 仅存储在服务器上,因为用户必须在 token 生命周期内保持登录状态。但是将其存储为 cookie 会使它容易受到攻击(我对这种攻击还不够熟悉,无法防范)。
我目前在收到 token 时有这一行:
res.cookie('authToken', response.access_token);
我还将该行调整为以下内容,因为这说明要删除所有通过脚本读取 cookie 的方式(这就够了吗?):
res.cookie('authToken', response.access_token, { httpOnly: true });
当访问网络界面的其他部分时,我会检查 cookie 是否存在,并尝试向 Discord 询问有关用户信息的信息。如果用户信息正确返回,我认为用户已正确通过身份验证:
router.get('/', catchAsync(async (req, res, next) => {
if(req.cookies.authToken === undefined) {
// Render index view
res.render('index', {
authenticated: false
});
}
else {
// Grab the token
const localToken = req.cookies.authToken;
// Use the token to query user information
const response = await discordapi.GetDiscordUserDetails(localToken);
if(response.id) {
// Open the Index page and pass the username over
res.render('index', {
authenticated: true,
username: response.username,
userid: response.id,
avatarid: response.avatar
});
} else {
res.render('index', {
authenticated: false
});
}
}
}));
(我传递的“已验证” bool 值仅更改 html(快速 Handlebars )文档中登录按钮的可见性。您不能用它做任何其他事情。)
现在,由于我对此的了解有限,我几乎认为这是最糟糕的做法,我想改进(这个)。
另一种解决方案是将访问 token 存储在 Web 服务器本身的数据库中。所以基本上从不以任何方式向用户展示它。 但是,然后我需要一种将此 token 与用户匹配的方法,因此他们仍然需要某种带有信息的 cookie,我可以使用这些信息来获取 token 。 我认为如果将 token 在数据库中加密并且用户拥有解密它的 key ,那将是最佳选择。 但是,我不确定这是否再次安全,因为如果您读出 cookie,您仍然可以访问 token ,或者至少表现得好像您是那个特定用户。
那么保持 cookie 100% 安全是唯一的方法吗?我对此很陌生,尽管这很可能只是一个简单的 discord 服务器的小型 Web 界面,但我仍然希望正确执行此操作。
我还读到将 token 作为某种密码处理并将其包装到另一层“ session ”中是一种方法,但这听起来很复杂,我实际上不知道从哪里开始。
我希望有人能对此有所说明,因为安全是我真正害怕的事情。
感谢您的宝贵时间!
最佳答案
- 无聊的故事:
我想首先假设我已经看到网上银行应用程序发送身份验证 token 作为纯文本附加在 POST 中作为查询字符串。
话虽如此,开发人员必须做出的大部分安全考虑必须旨在保护后端结构,而不是防止用户在客户端遭到黑客攻击。 (显然,你会尽一切努力让最后一个假设变得不那么可信,但在道德和技术上都有一个限制。我的意思是,如果我连接到一个不安全的网络并且有人拦截了我的通信并设法对其进行解码,我认为这更多是我的错。)
无论如何,我将不再哲学化,但最后一个众所周知的观察是,永远不会有任何 100% 安全的解决方案。
- 真正的答案:
使用 httpOnly cookie 是传输和存储身份验证 token 的最简单、最安全的方式,但如果这还不够,还可以实现其他一些安全层。这只是一些想法,可能还有更多!
缩短 token 的生命周期并在一段时间不活动后关闭 session 服务器端。您必须保留事件 session 的记录,每个 session 都有其开始时间和事件 token 等。
IP 检查。如果 session 以来自美国的 IP 地址开始,五分钟后 IP 似乎来自菲律宾,您可能必须采取一些措施。
使用 AWS Cognito 等外部身份验证服务。但它不会做任何你自己做不到的事情。
实现多重身份验证。
与 IP 检查类似,您可以使用用户代理字符串作为种子来计算哈希值,并将其存储。当您对客户身份有疑问时,请检查它。
谈到哈希,您可以存储 token 并将哈希发送给用户。唯一的改进是它可以防止有人直接调用 Discord API(如果 API 没有过滤器)。例如,密码始终存储为哈希值。
前者的任意组合。
这个列表可以无限地继续下去,在我看来,过了某个时间点,您只会不必要地浪费时间和资源。只要记住银行在 URL 中发送代币,你就会感觉好多了。
关于javascript - 如何安全地存储 Discord(OAuth2) 用户的访问 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54275431/