如何安全地存储Discord(OAuth2)用户的访问令牌? [英] How to securely store the Access-Token of a Discord(OAuth2) User?

查看:51
本文介绍了如何安全地存储Discord(OAuth2)用户的访问令牌?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力寻找一种安全地保存访问令牌的方法,该访问令牌是我的Web应用程序在用户授权应用程序后从DiscordAPI中检索到的.

我正在为Discord Bot创建一个Web界面.在此重要的是,并非每个人都可以使用它.仅应允许特定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});

当访问Web界面的其他部分时,我检查cookie是否存在,并尝试向Discord询问有关它的用户信息.如果用户信息返回正确,则认为用户已通过身份验证:

  router.get('/',catchAsync(async(req,res,next)== >> {if(req.cookies.authToken ===未定义){//渲染索引视图res.render('index',{已验证:假});}别的 {//获取令牌const localToken = req.cookies.authToken;//使用令牌查询用户信息const response =等待discordapi.GetDiscordUserDetails(localToken);if(response.id){//打开索引页面,并将用户名传递给res.render('index',{已验证:是,用户名:response.username,用户ID:response.id,头像:response.avatar});} 别的 {res.render('index',{已验证:假});}}})); 

(我正在传递的经过身份验证的"布尔值仅更改html(快速车把)文档中登录按钮的可见性.您无法对其进行任何其他操作.)

现在,由于我对此知识的了解有限,我几乎认为这是最糟糕的方法,我想对此加以改进.

另一种解决方案是将访问令牌存储在Web服务器本身的数据库中.因此,基本上根本不会以任何方式将其显示给用户.但是,然后,我需要一种将该令牌与用户匹配的方式,因此他们仍然需要某种cookie,其中包含我可以用来获取令牌的信息.我认为,如果令牌将在数据库中加密并且用户具有解密它的密钥,那将是最佳选择.但是,我不确定这是否再次安全,因为如果您读出cookie,您仍然可以访问令牌,或者至少表现得像是该特定用户一样.

那么保持cookie百分百安全的唯一方法是吗?我对此很陌生,即使这很可能只是一个简单的不和谐服务器的一个小型Web界面,我仍然想正确地做到这一点.

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

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

感谢您的时间!

解决方案

  • 无聊的故事:

我首先要假设已经看到在线银行应用程序将身份验证令牌发送为纯文本,并将其作为纯文本添加到POST中的查询字符串中.

话虽这么说,开发人员必须做出的大多数安全考虑都必须旨在保护后端结构,而不是防止用户被客户端黑客.(显然,您将尽一切可能使最后一个假设变得不太合理,但从道德和技术上讲,这是一个限制.我的意思是,如果我连接到一个非安全网络,并且有人拦截了我的通信并设法对其进行解码,我认为这将是我比别人更多的错.)

无论如何,我将不再是哲学上的,但最后一次已知的观察将永远不会为任何事情提供100%安全的解决方案.

  • 真正的答案:

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

  1. 减少令牌的生存时间,并在一段时间不活动之后关闭服务器端的会话.您将必须保存一个活动会话的记录,每个会话都包含其开始时间和活动令牌等.

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

  3. 使用外部身份验证服务,例如AWS Cognito.但这无能为力,这是您无法独自完成的.

  4. 实施多重身份验证.

  5. 类似于IP检查,您可以使用用户代理字符串作为种子来计算哈希并将其存储.如果您对客户身份有疑问,请进行检查.

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

  7. 上一个的任何组合.

该列表可能会无限增加,在我看来,经过一段时间后,您将只会不必要地浪费时间和资源.只需记住在URL中发送令牌的银行,您就会感觉好多了.

I'm struggling to find a way to securely save an Access-Token, which my web application retrieved from the DiscordAPI after the user authorized the application.

I'm creating a web-interface for a Discord Bot. Here it is important, that not everyone can use it. Only server-moderators and such on a specific Discord server should be allowed to access most parts of the website. For this I'm using the OAuth2 stuff from Discord to retrieve an Access-Token with which I can get user info, such as their unique ID. The ID is then used to check what sort of roles they have on the Discord server.

Now the part of getting the Access-Token is already scripted and seems to work okay. I can use the token to query data from the Discord API etc.

My main concern is security here. I've read through several different posts, but everyone seems to have a different view on this.

One "solution" I often read about (even on the Auth2 website) is to save the token in a cookie.

Here I'm not sure if that is secure at all. I can't simply store the token only on the Server, cause the user has to stay logged during the tokens lifetime. But storing it as a cookie opens it up to attacks (which I'm not familiar enough with to secure against).

I currently have this line when receiving the token:

res.cookie('authToken', response.access_token);

I also adjust the line to the following, as this is stated to remove all ways of reading out the cookies through scripts (is that enough?):

res.cookie('authToken', response.access_token, { httpOnly: true });

And when accessing other parts of the web interface, I check if the cookie exists and try to ask Discord about the user info with it. If the user info returns correctly I assume the user is properly authenticated:

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
            });
        }
   }
}));

(The "authenticated" boolean I am passing only changes visibility of the login button in the html (express handlebars) doc. You can't do anything else with it.)

Now with my limited knowledge about this, I pretty much assume this is the worst way of doing it and I want to improve (this).

Another solution would be storing the Access-Token in a Database on the Web-Server itself. So basically never even showing it to the user in any way. However, then I need a way of matching this token with the user, so they still need some sort of cookie with information which I can use to get the token. I assume it would be optimal if the token would be encrypted in the database and the user has a key to decrypt it. However then I'm not sure if that is secure again, cause if you read out the cookie, you can still get access to the token, or at least act like you are that specific user.

So is keeping the cookies 100% secure the only way? I'm very new to this and even though this is most likely only a small web interface for one simple discord server, I still want do this correctly.

I also read that handling the token as some sort of password and wrapping it into another layer of "sessions" is a way of doing it, but that sounds overlay complicated and I would actually not know where to begin with this.

I hope someone can shed some light on this, as security is something I'm really afraid of.

Thanks for your time!

解决方案

  • BORING STORY:

I would like to start with the premise that I have seen online banking applications sending authentication tokens as plain text appended as a query string in a POST.

With that being said, most of the security considerations a developer has to make must aim to protect the back-end structure and not to prevent users from being hacked client-side. (Obviously, you will make everything you can to make that last hypothesis less plausible, but there is a limit, morally and technologically. I mean, if I connect to a non-secure network and someone intercepts my communication and manages to decode it, I think it would be more my fault than others.)

Anyway, I will stop being philosophical, but a last, already known, observation, there will be never a 100% secure solution for anything.

  • THE REAL ANSWER:

Using httpOnly cookies is the most simple and secure way to transmit and store authentication tokens, but if that is not enough, there are some other security layers that can be implemented. This are only some ideas, there could be many more!

  1. Reduce tokens lifetime and close session server-side after some inactivity time. You will have to keep a record with the active sessions, each one with its starting time and active token, etc.

  2. IP check. If a session started with an IP address from the US, and five minutes later the IP seems to be from Philippines, probably you have to take some action.

  3. Use external authentication services like AWS Cognito. But it will do nothing that you can not do on your own.

  4. Implement Multi-Factor Authentication.

  5. Similar to the IP check, you could calculate a hash using a user agent string as a seed, and store it. Check it when you have doubts about client identity.

  6. Talking about hashes, you can store the token and send a hash to the user. The only improvement is that it prevents someone from calling the Discord API directly (if the API has no kind of filter). Passwords, for example are always stored as hashes.

  7. Any combination of the previous.

The list could go on infinitely, and after some point, in my opinion, you will be only losing time and resources unnecessarily. Just remember the banks sending the tokens in the URL, and you will feel a lot better.

这篇关于如何安全地存储Discord(OAuth2)用户的访问令牌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆