简体   繁体   English

Node.js-是否需要解码身份验证令牌?

[英]Nodejs - Is it necessary to decode an Authentication Token?

I am using a combination of Node.js and Passportjs on the server-side, and Emberjs on the client side for an app. 我在服务器端结合使用Node.js和Passportjs,在客户端结合使用Emberjs作为应用程序。 My current Authentication strategy is to use Passport-Local to authenticate users with normal email/password combinations as standard, and then hook in a session creation mechanism to generate an Authentication Token, which is saved into a separate table, and passed back to the user for use in any further protected routes. 我当前的身份验证策略是使用Passport-Local以标准的常规电子邮件/密码组合对用户进行身份验证,然后使用会话创建机制来生成身份验证令牌,该身份验证令牌将保存到单独的表中并传递回用户用于其他受保护的路线。 (passed in the REST header). (在REST标头中传递)。

Creation of the token is fine, i'm doing that without issue, however i'm struggling to work out if I need an extra step. 令牌的创建很好,我这样做没有问题,但是如果我需要额外的步骤,我会努力工作。

Currently, I generate the token with node-jwt-simple by using a random node-uuid pass as the payload, and the users UID (another node-uuid ) as the secret. 当前,我通过使用一个随机的node-uuid传递作为有效负载,并使用用户UID(另一个node-uuid )作为秘密,使用node-jwt-simple生成令牌。 I then save this to a $.cookie on the clientside, and to a table on the serverside, along with a creation date. 然后,我将其保存到客户端的$.cookie和服务器端的表以及创建日期。

Obviously, one of the steps in node-jwt-simple is to encode the token. 显然, node-jwt-simple中的步骤之一是对令牌进行编码。 There is also a decode function provided. 还提供了解码功能。 My question is, do I need to decode the token into something when I am doing my auth checking, or is simply checking the user's session cookie (REST header) for a match against the token in the database sufficient? 我的问题是,在进行身份验证检查时是否需要将令牌解码为某种东西,还是只是检查用户的会话cookie(REST标头)是否足以与数据库中的令牌匹配? I wouldn't want to go to all the effort of having generated a token, only to then miss an important step, but i'm not seeing how I could decode it into anything that would provide any additional useful security. 我不想花所有的精力来生成令牌,只是想错过一个重要的步骤,但是我看不到如何将其解码为可以提供任何其他有用安全性的东西。

UPDATE: 更新:

I think I worked this out last night: 我想我昨天晚上解决了这个问题:

The solution seems to be to use the User's UID as the payload for JWT, with a static string as the secret (taken from something like a server environment variable or similar), and then only store the encoded token in the database. 解决方案似乎是使用用户的UID作为JWT的有效负载,并使用静态字符串作为秘密(从类似服务器环境变量之类的东西中获取),然后仅将编码的令牌存储在数据库中。 Pass the token back to the client for re-auth, then when the client attempts to access a protected route, they must pass their UID along with the encoded token to the server, which is then decoded, and the decoded payload compared to the UID that has been passed. 将令牌传递回客户端以进行重新身份验证,然后,当客户端尝试访问受保护的路由时,他们必须将其UID连同编码的令牌一起传递给服务器,然后将其解码,并将解码后的有效载荷与UID进行比较已经通过了。 If they match, the auth is successful, otherwise the token is destroyed and the user has to log in again. 如果它们匹配,则身份验证成功,否则令牌将被破坏,用户必须再次登录。 By doing this, it makes the store of tokens effectively useless without knowing either the Secret key, or having the User's UID, but makes the auth process more secure. 这样,它使令牌存储实际上无用,而无需知道密钥或用户的UID,但使身份验证过程更加安全。

If you don't validate the token, you could as well create some other random data to use as a session cookie, as long as it is unique and cannot be guessed by clients. 如果您不验证令牌,则还可以创建其他一些随机数据以用作会话cookie,只要它是唯一的并且不能被客户端猜测即可。

But as you already made a lot of effort, you could encode something useful in the token which tells you how long it is valid, eg an exp field, so you don't have to read from the database. 但是,由于您已经做了很多工作,因此可以在令牌中对有用的东西进行编码,以告诉您令牌有效的时间,例如exp字段,因此您不必从数据库中读取数据。

I'm not sure if I fully understand your JWT, but the problem I see is that you need information to decode the token which is probably not at your hand. 我不确定我是否完全了解您的JWT,但是我看到的问题是,您需要信息来解码令牌,而这可能不是您的手。 So you have to do a search in your database. 因此,您必须在数据库中进行搜索。

I think it would be sufficient to use some random session key, eg following function: 我认为使用一些随机的会话密钥就足够了,例如以下功能:

var crypto = require('crypto');

/**
 * Create random bytes and encode base64url.
 * @param {int} [lengthInBytes=40] the size of the raw token in bytes
 *        (will be longer since base64url-encoded)
 * @param {function} callback node-style callback-function;
 *        data-parameter is a string w/ a shortened (no trailing ==)
 *        base64url-encoded string of the generated bytes.
 */
exports.createRandomToken = function createRandomToken(lengthInBytes, callback) {
    if (typeof lengthInBytes === 'function') {
        callback = lengthInBytes;
        lengthInBytes = 40;
    }
    crypto.randomBytes(lengthInBytes, function (ex, buf) {
        if (ex) {
            callback(ex);
            return;
        }
        callback(null, buf.toString('base64')
                          .replace(/\//g, '_')
                          .replace(/\+/g, '-')
                          .replace(/=/g, ''));
    });
};
  1. Set expire time of the token as small as possible(5 min, 30 min, nor months neither years). 将令牌的过期时间设置得尽可能短(5分钟,30分钟,也不要几个月,也不是两年)。
  2. Use refresh token to get a new token and update refresh token every time you update old token (and when user is logged in, no doubt) 每次更新旧令牌时,都使用刷新令牌来获取新令牌并更新刷新令牌(毫无疑问,当用户登录时)
  3. Do not store passwords, credit card numbers and any confidential informations in the token ( I'm shure, you know it :) ) 不要在令牌中存储密码,信用卡号和任何机密信息(我敢保证,您知道:))
  4. Store all necessary information for checking privileges ( or checking ip, for example ). 存储用于检查特权(或检查ip)的所有必要信息。 It is good for REST API and horizontal scaling. 这对于REST API和水平缩放非常有用。

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

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