我正在努力寻找一种安全保存访问令牌的方法,我的 Web 应用程序在用户授权应用程序后从 DiscordAPI 检索到该访问令牌。
我正在为 Discord 机器人创建一个网络界面。重要的是,不是每个人都可以使用它。仅应允许特定 Discord 服务器上的服务器版主等访问网站的大部分内容。为此,我使用 Discord 中的 OAuth2 内容来检索访问令牌,通过它我可以获取用户信息,例如他们的唯一 ID。
然后,该 ID 用于检查他们在 Discord 服务器上拥有的角色类型。
现在获取访问令牌的部分已经编写好并且似乎工作正常。我可以使用令牌从 Discord API 等查询数据。
我主要关心的是这里的安全。我读过几篇不同的文章,但每个人似乎对此都有不同的看法。
我经常读到的一种“解决方案”(甚至在 Auth2 网站上)是将令牌保存在 cookie 中。
在这里我不确定这是否安全。我不能简单地将令牌仅存储在服务器上,因为用户必须在令牌生命周期内保持登录状态。但将其存储为 cookie 会导致其遭受攻击(我对此不太熟悉,无法防范)。
我目前在收到令牌时有这一行:
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
});
}
}
}));
(我传递的“已验证”布尔值仅更改 html(快速手柄)文档中登录按钮的可见性。您不能用它做任何其他事情。)
现在,由于我对此的了解有限,我几乎认为这是最糟糕的方法,我想改进(这一点)。
另一种解决方案是将访问令牌存储在 Web 服务器本身的数据库中。所以基本上永远不会以任何方式向用户展示它。
但是,然后我需要一种将此令牌与用户相匹配的方法,因此他们仍然需要某种带有我可以用来获取令牌的信息的 cookie。
我认为如果令牌在数据库中被加密并且用户有一个密钥来解密它,那将是最佳的。
然而,我不确定这是否再次安全,因为如果您读出 cookie,您仍然可以访问令牌,或者至少表现得像您是该特定用户一样。
那么保持 cookie 100% 安全是唯一的方法吗?我对此很陌生,尽管这很可能只是一个简单的不和谐服务器的小型网络界面,但我仍然想正确地做到这一点。
我还读到,将令牌处理为某种密码并将其包装到另一层“会话”中是一种方法,但这听起来很复杂,我实际上不知道从哪里开始。
我希望有人能对此有所了解,因为安全是我真正担心的事情。
谢谢你的时间!