无效JSON网络令牌无效JSON网络令牌(Invalidating JSON Web Tokens)

2019-05-09 01:52发布

对于一个新的node.js的项目我的工作,我想从一个基于cookie的会话方式切换(由这一点,我的意思是,存储的ID包含用户的浏览器用户会话键值存储)使用JSON网络令牌(JWT)基于令牌的会话方式(键 - 值存储)。

该项目是一个游戏,利用socket.io - 具有基于令牌的会议将是在这种情况下有用,都会有一个会话多个沟通渠道(网络和socket.io)

一个人怎么会从提供使用JWT方法服务器令牌/会话失效?

我也想了解普通(或罕见的)陷阱/攻击我应该看出来的与这种范式。 例如,如果这种模式很容易受到相同/不同种类的作为会话存储/基于cookie的方法攻击。

所以,说我有以下(改编自这个和这个 ):

会话存储登录:

app.get('/login', function(request, response) {
    var user = {username: request.body.username, password: request.body.password };
    // Validate somehow
    validate(user, function(isValid, profile) {
        // Create session token
        var token= createSessionToken();

        // Add to a key-value database
        KeyValueStore.add({token: {userid: profile.id, expiresInMinutes: 60}});

        // The client should save this session token in a cookie
        response.json({sessionToken: token});
    });
}

基于令牌登录:

var jwt = require('jsonwebtoken');
app.get('/login', function(request, response) {
    var user = {username: request.body.username, password: request.body.password };
    // Validate somehow
    validate(user, function(isValid, profile) {
        var token = jwt.sign(profile, 'My Super Secret', {expiresInMinutes: 60});
        response.json({token: token});
    });
}

-

一种用于会话存储方式退出(或无效)将需要更新到KeyValueStore数据库与指定的标记。

这似乎是这种机制不会在基于令牌的方式存在的,因为令牌本身就包含将在键值存储通常存在的信息。

Answer 1:

我也一直在研究这个问题,而没有下面的想法是完整的解决方案,他们可以帮助他人排除的想法,或提供更多的类型。

1)只要从客户端删除该令牌

显然,这无助于服务器端的安全性,但它确实通过去除存在令牌停止攻击者(即他们将不得不偷注销之前令牌)。

2)创建令牌黑名单

您可以在无效令牌存储,直到他们最初的有效期限,并比较他们对传入的请求。 这似乎是否定的理由去根据放在首位完全令牌来,因为你需要触摸数据库为每个请求。 存储大小可能会更低不过,因为你只需要存储是注销和到期时间(这是一种内心的感觉,绝对是依赖于上下文)之间的令牌。

3)只要保持令牌到期时间短,往往使它们旋转

如果你保持令牌到期时间在足够短的时间间隔,并有运行的客户端跟踪和更新的要求,必要时,1号将有效地工作,作为一个完整的系统注销。 用这种方法的问题是,它使得它不可能保持用户(取决于您做出到期间隔多长时间)的客户端代码的关闭之间登录。

临时计划

如果有曾经是一个紧急情况,或用户令牌被攻破,有一两件事你可以做的是允许用户更改底层用户查找ID与他们的登录凭据。 这将使所有相关的令牌无效,因为相关的用户将不再能够被发现。

我也想指出,这是一个好主意,包括上次登录的日期与令牌,让你能够在一段遥远的时间后强制执行重新登录。

在与关于使用令牌攻击相似/差异而言,这篇文章解决了问题: http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/



Answer 2:

上面贴的想法是好的,但一个非常简单和容易的方法无效所有现有JWTs仅仅是改变的秘密。

如果您的服务器创建JWT,用秘密(JWS)然后将其发送给客户端,简单地改变秘密遗嘱无效所有现有的令牌,并要求所有用户获得一个新的令牌来验证他们的老令牌根据无效突然变得迹象它到服务器。

它不需要实际令牌的内容(或者查找ID)的任何修改。

显然,这仅适用于当你想要的所有现有令牌到期,对于每个令牌到期上面的解决方案之一是必需的(如短令牌到期时间或无效令牌内存储的密钥)的紧急情况时。



Answer 3:

这主要是一个长注释支持和@mattway建设对答案

鉴于:

一些在此页面主张打在每次请求数据存储中的其他提出的解决方案。 如果你打的主数据存储,以验证每一个认证请求,然后我看到一个可使用智威汤逊,而不是等建立令牌认证机制少的原因。 你基本上由智威汤逊状态,而不是无状态的,如果你每次都去的数据存储。

(如果您的网站未授权接收请求的高容量,那么JWT会否认他们没有击中的数据存储,这是有帮助的。可能有其他的用例这样的。)

鉴于:

真正的无状态JWT认证不能为典型的,真实世界的Web应用程序来实现,因为无国籍JWT没有办法提供了以下重要的用例直接安全的支持:

用户的帐户被删除/阻止/暂停。

用户密码已更改。

用户的角色或权限被更改。

用户通过管理员注销。

在JWT令牌任何其他应用程序的关键数据是由网站管理员改变。

你不能等待在这些情况下令牌到期。 令牌无效,必须立即发生。 此外,你不能相信客户端不保留并使用旧令牌的副本,无论是恶意或不。

因此:我想答案从@亚光路,#2 TokenBlackList,将所要求的状态添加到基于JWT认证最有效的方式。

你有,直到他们的到期日被击中持有这些令牌的黑名单。 令牌的名单将是非常小的相比,用户总数,因为它只有保持黑名单标记,直到其到期。 我想通过把无效的令牌redis的,分布式缓存或另一个内存数据存储区支持上的键设置过期时间的实施。

您还必须对您的内存数据库对于通过初步JWT AUTH每个认证请求的电话,但你不必存储密钥为您的整个用户群在那里。 (这可能会或可能不会是一个大问题,对于一个给定的网站。)



Answer 4:

我会保持对用户模型中的智威汤逊版本号的记录。 新智威汤逊令牌将其版本设置为这个。

当您验证的智威汤逊,简单地检查它的版本号等于用户的当前JWT版本。

任何时候你要作废的老jwts,只是颠簸的用户JWT版本号。



Answer 5:

没有试过呢,它是采用基于一些其他的答案中的大量信息。 这里的复杂性,以避免每个请求的服务器端数据存储调用用户信息。 大多数其他解决方案都需要每个请求一个数据库查找到用户会话存储。 这是在某些情况下罚款,但这个是在试图避免这种电话和作出一切必需的服务器端状态是非常小的创建。 你最终将再造一个服务器端的会话,无论多小,提供所有的力失效功能。 但是,如果你想在这里做的是要点:

目标:

  • 减轻使用的数据存储器(无状态)的。
  • 能够强制注销所有用户。
  • 能够迫使随时注销任何个人。
  • 能力需要一定的时间后,密码重新输入。
  • 能力与多个客户一起工作。
  • 能够强制重新登录时,用户点击来自特定客户端退出。 (为了防止有人“取消删除”客户端令牌用户走开后 - 更多信息参见注释)

解决方案:

  • 使用与寿命较长(几个小时)配对短暂的(<5M)访问令牌的客户端存储刷新令牌 。
  • 每个请求检查或者在auth或刷新有效性令牌到期日期。
  • 当访问令牌到期时,客户端使用刷新令牌刷新访问令牌。
  • 在刷新令牌检查,服务器会检查用户ID的小黑名单 - 如果发现拒绝更新请求。
  • 当客户端没有一个有效的(未过期)刷新或身份验证令牌,用户必须重新登录,因为所有其他请求将被拒绝。
  • 在登录请求,检查用户数据存储的禁令。
  • 在注销 - 用户添加到会话黑名单,使他们不得不重新登录,您将不得不存储更多的信息在多设备环境无法登录他们的所有设备,但它可以通过增加设备领域的工作要做。用户黑名单。
  • 要强制后的时间x量再入 - 保持在身份验证令牌最后一次登录的日期,并检查每个请求。
  • 要强制注销所有用户 - 重置令牌的哈希键。

这需要你在服务器上维护一个黑名单(州),假设用户表中包含禁止用户信息。 无效的会话黑名单 - 是用户ID的列表。 这个黑名单刷新令牌请求时只检查。 参赛作品要求只要刷新令牌TTL住就可以了。 一旦刷新令牌到期,用户将需要重新登录。

缺点:

  • 仍然需要做的刷新令牌请求的数据存储查询。
  • 无效的令牌可以继续访问令牌的TTL操作。

优点:

  • 提供所需的功能。
  • 刷新令牌行动是从在正常操作的用户隐藏。
  • 只需要做刷新请求,而不是每个请求的数据存储查询。 即每隔1 15分钟而不是1每秒。
  • 最大限度地减少服务器端的状态,以一个非常小的黑名单。

随着不需要像reddis内存数据存储这种解决方案的,至少不会对用户信息和你一样的服务器仅制作DB调用每隔15分钟左右。 如果使用reddis,存储将有一个非常快速和简单的解决方案的有效/无效的会话列表。 无需刷新令牌。 每个身份验证令牌将有一个会话ID和设备ID,可以把它们存储在reddis表上创建并被禁止在适当的时候。 然后,他们会在每次请求进行检查和拒绝时无效。



Answer 6:

我一直在考虑的一个方法是始终有一个iat在智威汤逊(在发行)值。 然后,当用户注销时,存储在用户记录该时间戳。 当验证JWT只是比较iat到最后注销的时间戳。 如果iat是旧的,那么它是不是有效。 是的,你必须去到DB,但我会永远反正拉动用户记录,如果智威汤逊,否则无效。

主要缺点我看到的情况是,它会记录他们出去他们的所有会话,如果他们在多个浏览器,或拥有移动客户端了。

这也可能是系统中的所有JWTs无效一个很好的机制。 在检查的一部分可能是对的最后一个有效全局时戳iat时间。



Answer 7:

我有点晚了这里,但我想我有一个体面的解决办法。

我在我的数据库中的“last_password_change”列存储当密码上次更改的日期和时间。 我也存储在JWT日期/问题的时间。 当验证令牌,我检查令牌发出后的密码已更改,如果这是即使尚未到期的令牌被拒绝。



Answer 8:

你可以在你的用户的文件/记录您的数据库是“last_key_used”字段。

当用户与用户登录并通过,产生一个新的随机字符串,将其存储在last_key_used领域,并签署令牌时增加了有效载荷。

当用户登录使用令牌,检查last_key_used在DB相匹配的一个令牌。

然后,当用户执行注销的情况下,或者如果你想令牌无效的,仅仅是“last_key_used”字段更改为另一个随机值及任何后续检查将失败,从而迫使用户与用户登录,并再次通过。



Answer 9:

  1. 给出令牌1天到期时间
  2. 保持每日黑名单。
  3. 把无效/注销令牌进黑名单

对于令牌验证,检查令牌到期时间,然后再黑名单,如果令牌没有过期。

对于长会议的需求,应该有延长令牌到期时间的机制。



Answer 10:

迟到了,我的两分钱下面给出一些研究之后。 在注销,请确保以下事情发生...

清除客户端存储/会话

更新用户表上次登录的日期,时间和注销日期,时间,只要登录或注销分别发生。 所以,登录日期时间总是应大于注销大于(或保留的注销日期为空,如果当前状态登录并没有登出)

这是不是保持黑名单的附加表,并定期清洗方式远简单。 多种设备支持需要额外表保持的loggedIn,与像OS-或客户的详细资料其他一些细节注销日期。



Answer 11:

保持在内存中的列表是这样

user_id   revoke_tokens_issued_before
-------------------------------------
123       2018-07-02T15:55:33
567       2018-07-01T12:34:21

如果您的令牌在一个星期内到期再用干净的或忽略的记录比老。 也只保留每个用户的最新记录。 该列表的大小将取决于多久你保持你的令牌和频率的用户撤销其令牌。 使用DB只有当表的变化。 加载表中存储你的应用程序启动时。



Answer 12:

为什么不直接使用日本烟草国际公司要求(随机数),并存储在列表中的用户记录字段(DB依赖,但最起码​​一个逗号分隔的列表是罚款)? 无需单独的查询,正如其他人指出,想必你想获得用户记录无论如何,这样一来,你也可以根据不同的客户实例的多个有效令牌(“登出无处不在”可以重新设置列表为空)



Answer 13:

我做了以下的方法:

  1. 生成一个unique hash ,然后将其存储在Redis的和你的智威汤逊 。 这可以被称为会话
    • 我们也将存储在特定的智威汤逊做出了请求的数量-每次JWT被发送到服务器,我们增加了请求整数。 (这是可选的)

因此,当用户登录时,一个唯一的哈希创建,存储在Redis的,并注入到你的智威汤逊

当用户试图访问受保护的终点,你会抓住从你的智威汤逊 ,查询Redis的唯一会话哈希,看看它是否是一个比赛!

我们可以从这个扩展,使我们的智威汤逊更加安全,方法如下:

每个X请求特定的智威汤逊做出了,我们生成一个新的唯一的会话,它存储在我们的智威汤逊 ,然后黑名单上一个。

这意味着, 智威汤逊是不断变化的,停止的陈旧JWT被黑客入侵,被盗或别的东西。



Answer 14:

如果你希望能够撤销用户令牌,你可以保持你的数据库中的所有发布的令牌的跟踪和检查,如果他们是在一个会话,如表有效的(存在)。 缺点是,你会打DB在每次请求。

我还没有尝试过,但我建议以下方法,以允许撤销凭证,同时保持DB命中降到最低 -

为了降低数据库检查率,根据一些确定性关联(例如,10组由用户ID的第一个数字)除以所有发出JWT令牌,X基团。

每个JWT令牌将保持组ID,并在令牌创建创建一个时间戳。 例如, { "group_id": 1, "timestamp": 1551861473716 }

服务器将保存所有组ID在内存中,每个小组将有一个时间戳指示何时是属于该组的用户的最后注销事件。 例如, { "group1": 1551861473714, "group2": 1551861487293, ... }

与JWT令牌有一个老年组时间戳,请求将其有效性进行检查(DB命中),如果有效,用新鲜的时间戳的新JWT令牌将客户端的将来使用发行。 如果令牌的组时间戳更新,我们相信智威汤逊(无DB命中)。

所以 -

  1. 我们只验证使用DB一个JWT令牌如果令牌有一个年龄组的时间戳,而将来的请求将不会得到验证,直到有人在用户组将注销英寸
  2. 我们使用组来限制的时间戳更改的数量(比如有进出一个用户登录像没有明天 - 将只影响用户,而不是每个人的数量有限)
  3. 我们限制组的数量限制时间戳保存在内存量
  4. 无效令牌是一件轻而易举的 - 刚刚从会话表中删除,并为用户的组新的时间戳。


Answer 15:

如果“所有设备退出”选项是可以接受的(在大多数情况下它是):

  • 令牌版本字段添加到用户记录。
  • 在此字段中添加值存储在智威汤逊的说法。
  • 每次用户注销时增加版本。
  • 验证当令牌其版本要求与存储在用户记录的版本,并拒绝如果它是不一样的。

一个分贝之旅获得在大多数情况下所以这并没有多大的开销增加了验证过程无论如何都需要用户记录。 不同于保持黑名单,其中DB负荷显著由于需要使用连接或单独的呼叫,干净的旧记录等。



Answer 16:

每个用户独特的字符串,以及全球串在一起散列

担任JWT秘密部分允许个人和全球令牌无效。 在一个分贝查找/成本请求AUTH期间读取的最大的灵活性。 也容易缓存为好,因为它们很少发生变化。



Answer 17:

我只保存令牌的用户表中,当用户登录我会更新新的令牌,当AUTH等于用户当前JWT。

我觉得这是不是最好的解决办法,但对我来说工作。



Answer 18:

如果你简单地生成从expiresIn服务器一个新的令牌:0,并给它返回到客户端,并将其存储在cookie?



文章来源: Invalidating JSON Web Tokens