简体   繁体   English

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

[英]How to securely store the Access-Token of a Discord(OAuth2) User?

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.我正在努力寻找一种安全保存访问令牌的方法,我的 Web 应用程序在用户授权应用程序后从 DiscordAPI 检索到该令牌。

I'm creating a web-interface for a Discord Bot.我正在为 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.只有特定 Discord 服务器上的服务器版主等才能访问网站的大部分内容。 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.为此,我使用 Discord 中的 OAuth2 来检索访问令牌,我可以使用它获取用户信息,例如他们的唯一 ID。 The ID is then used to check what sort of roles they have on the Discord server.然后使用 ID 来检查他们在 Discord 服务器上的角色类型。

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.我可以使用令牌从 Discord API 等查询数据。

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.我经常读到的一个“解决方案”(甚至在 Auth2 网站上)是将令牌保存在 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).但是将其存储为 cookie 会使其受到攻击(我不太熟悉,无法防范)。

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?):我还将该行调整为以下内容,因为这是为了删除通过脚本读取 cookie 的所有方式(这足够了吗?):

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.当访问 Web 界面的其他部分时,我会检查 cookie 是否存在并尝试向 Discord 询问用户信息。 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.) (我传递的“经过身份验证的”布尔值仅更改 html(快速车把)文档中登录按钮的可见性。您不能用它做任何其他事情。)

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.另一种解决方案是将访问令牌存储在 Web 服务器本身的数据库中。 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.但是,然后我需要一种将这个令牌与用户匹配的方法,所以他们仍然需要某种带有信息的 cookie,我可以用它来获取令牌。 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.但是,我不确定这是否再次安全,因为如果您读出 cookie,您仍然可以访问令牌,或者至少表现得好像您是该特定用户。

So is keeping the cookies 100% secure the only way?那么保持 cookie 100% 安全是唯一的方法吗? 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.我对此很陌生,尽管这很可能只是一个简单的不和谐服务器的小型 Web 界面,但我仍然希望正确执行此操作。

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.我想从我看到在线银行应用程序发送身份验证令牌作为在 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.无论如何,我将不再哲学化,但最后一个已经知道的观察,对于任何事情都不会有 100% 安全的解决方案。

  • 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.使用 httpOnly cookie 是传输和存储身份验证令牌的最简单和安全的方式,但如果这还不够,还有一些其他安全层可以实现。 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. IP检查。 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.如果会话以来自美国的 IP 地址开始,而五分钟后该 IP 似乎来自菲律宾,则您可能需要采取一些措施。

  3. Use external authentication services like AWS Cognito.使用 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.与 IP 检查类似,您可以使用用户代理字符串作为种子来计算哈希值并存储它。 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).唯一的改进是它可以防止有人直接调用 Discord API(如果 API 没有过滤器)。 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.只要记住银行在 URL 中发送令牌,你就会感觉好多了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM