如何安全地存储 Discord(OAuth2) 用户的访问令牌?

2024-04-29

我正在努力寻找一种安全保存访问令牌的方法,我的 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% 安全是唯一的方法吗?我对此很陌生,尽管这很可能只是一个简单的不和谐服务器的小型网络界面,但我仍然想正确地做到这一点。

我还读到,将令牌处理为某种密码并将其包装到另一层“会话”中是一种方法,但这听起来很复杂,我实际上不知道从哪里开始。

我希望有人能对此有所了解,因为安全是我真正担心的事情。

谢谢你的时间!


  • 无聊的故事:

我想首先假设我看到在线银行应用程序以纯文本形式发送身份验证令牌,并在 POST 中作为查询字符串附加。

话虽如此,开发人员必须考虑的大部分安全考虑必须旨在保护后端结构,而不是防止用户在客户端被黑客攻击。 (显然,你会尽一切努力使最后一个假设不太可信,但在道德和技术上都有一个限制。我的意思是,如果我连接到一个不安全的网络并且有人拦截我的通信并设法对其进行解码,我认为这更多是我的错,而不是其他人的错。)

无论如何,我将不再哲学化,但最后一个已知的观察结果是,任何事情都不会有 100% 安全的解决方案。

  • 真正的答案:

使用 httpOnly cookie 是传输和存储身份验证令牌的最简单、最安全的方法,但如果这还不够,还可以实现一些其他安全层。这只是一些想法,可能还有更多!

  1. 减少令牌生命周期并在一段不活动时间后关闭会话服务器端。您必须保留活动会话的记录,每个会话都有其开始时间和活动令牌等。

  2. IP 检查。如果会话以美国的 IP 地址开始,五分钟后该 IP 似乎来自菲律宾,则您可能必须采取一些操作。

  3. 使用 AWS Cognito 等外部身份验证服务。但它不会做任何你自己做不到的事情。

  4. 实施多重身份验证。

  5. 与 IP 检查类似,您可以使用用户代理字符串作为种子来计算哈希值,并将其存储。当您对客户身份有疑问时请检查它。

  6. 谈到哈希值,您可以存储令牌并将哈希值发送给用户。唯一的改进是它可以防止某人直接调用 Discord API(如果该 API 没有任何类型的过滤器)。例如,密码始终存储为哈希值。

  7. 先前的任意组合。

这个清单可以无限地继续下去,在我看来,在某个时刻之后,你只会不必要地浪费时间和资源。只要记住银行在 URL 中发送令牌,您就会感觉好很多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何安全地存储 Discord(OAuth2) 用户的访问令牌? 的相关文章

随机推荐

  • ipad 2相机支持检测

    我有一个使用以下宏的应用程序 define IS IPAD UIDevice currentDevice respondsToSelector selector userInterfaceIdiom UIDevice currentDevi
  • 将 Android 应用程序部署到手机:错误:[install_itemfolder_01] 错误 1 ​​Windows

    我已经安装了我可能需要的所有组件 我已经上网两天了 但找不到这个问题的答案 我检查了我的 apache ant javac java JRE JDK Qt 变量一切正常 Qt 喜欢我的所有设置 除了当我尝试将应用程序部署到模拟器或设备时出现
  • 在 bash 中传递多个数组作为参数

    我已经成功地能够调用单个数组作为参数 但在传递多个数组时遇到问题 这是我到目前为止所拥有的 calling function array1 1 2 3 4 array2 a b c d array3 called function arra
  • 通过 Hyperledger Composer 中的交易创建资产

    在创建任何asset or 参与者需要检查一些条件就像 如果 那么 否则 在某些领域 是否可以创建Asset or 参加者通过交易 对的 这是可能的 我在我的网络中做了同样的事情 通过交易创建资产并应用您需要的任何规则 事务从 lib 中的
  • Google 组织结构图数据溢出到 div 之外

    我在一个项目中使用 Google Org 图表 图表的内容在包含的 div 之外流动 该 div 在下面以红色突出显示 我希望图表的节点能够移动到下一行 以防它流到 div 之外 爱丽丝将移动到下一行 数据将继续 See my 在这里摆弄
  • 小写表名错误

    我正在尝试设置lower case table name价值2 因为它是 Windows 服务器 但是当我启动 MySQL Workbench 并连接到我的服务器时 出现以下错误 服务器所在的系统不能正确支持所选的lower case ta
  • 具有默认值的 Asp.net webapi 枚举参数

    我有一个控制器 HttpGet RoutePrefix api products productId public HttpResponseMessage Products int productId TypeEnum ptype Type
  • 离开页面时 JQuery Ajax 错误

    我使用以下代码将数据从服务器异步提取到客户端 错误块中的警报报告服务器上发生的错误 但是 如果用户在调用过程中离开页面 该块也会被触发并抛出一个空的警报容器 有什么方法可以更优雅地处理用户离开页面的情况 即在离开之前不抛出空警报 也许可以通
  • 当加载图标且 tk.mainloop 位于线程中时,Tkinter 会锁定 Python

    这是测试用例 import Tkinter as tk import thread from time import sleep if name main t tk Tk thread start new thread t mainloop
  • 如何更改 Rx Builder 实现来修复堆栈溢出异常?

    我正在尝试提出一个 Rx Builder 以在 F 计算表达式语法中使用反应式扩展 我该如何修复它 以免堆栈崩溃 就像下面的 Seq 例子一样 是否有计划提供 RxBuilder 的实现作为响应式扩展的一部分或作为 NET Framewor
  • <%= foo %> 和 ${ foo } 之间的区别

    第一次在 JSP 中编码 我需要将变量的值呈现为 HTML 看起来有多种方法可以做到这一点 它们之间有什么区别 假设我有一个名为foo and foo 这 使用老式的输出小脚本这是十年来一直灰心丧气 https stackoverflow
  • 如何从字符串读取 NumPy 二维数组?

    如何从字符串中读取 Numpy 数组 取一个像这样的字符串 0 5544 0 4456 0 8811 0 1189 并将其转换为数组 a from string 0 5544 0 4456 0 8811 0 1189 where a成为对象
  • 我可以为 XPath 中缺失的标签创建一个值吗?

    我有一个使用 XPath 从 XML 文件中提取数据的应用程序 如果该 XML 源文件中的节点丢失 我想返回值 N A 很像 Oracle NVL 函数 问题在于该应用程序不支持 XSLT 我想使用 XPath 和单独使用 XPath 来完
  • Spring MVC 配置启用

    我正在从头开始建立一个项目 目前我正在配置Spring MVC 4 1 5使用java配置 整个应用程序正在 tomcat gradle 插件上运行 有人可以解释一下为什么我需要对班级进行以下调用DefaultServletHandlerC
  • 作为依赖项和不同的 publicKeyToken 共享时 RestSharp 错误

    使用来自的 APIDocusign Twilio and Auth0 全部 3 个都有RestSharp dll作为依赖 如果我使用RestSharp dll包含在Docusign包裹 Docusign效果很好但是Auth0 and Twi
  • 在 docker build 中缓存“go get”

    我想将 golang 单元测试封装在 docker compose 脚本中 因为它依赖于多个外部服务 我的应用程序有很多依赖项 因此需要一段时间go get 如何以允许构建 docker 容器的方式缓存包 而无需每次要测试时下载所有依赖项
  • 如何在 gitlab-ci 作业之间传递变量?

    我有一个像这样的 gitlab ci stages calculation execution calculation job stage calculation script calculate something and output
  • 如何使用 mongoTemplate 实现 Mongodb Collection 的分页

    我是 mongoDb 中的菜鸟 我需要为任何特定集合实现分页 例如说 我有一个 Foo 集合 并且有一个返回 Foo 集合中所有记录的函数 public List
  • Button.setImage(nil, for: .normal) 在 iOS 15 中不起作用

    我试图在 Swift 中制作一个简单的井字棋应用程序 所以我设置了 9 个带有从 1 到 9 标签的按钮并调用setImage设置圆圈和十字 这正在按预期工作 当尝试重置主板时出现问题 我将这段代码称为 for i in 1 lt 10 i
  • 如何安全地存储 Discord(OAuth2) 用户的访问令牌?

    我正在努力寻找一种安全保存访问令牌的方法 我的 Web 应用程序在用户授权应用程序后从 DiscordAPI 检索到该访问令牌 我正在为 Discord 机器人创建一个网络界面 重要的是 不是每个人都可以使用它 仅应允许特定 Discord