(从此线程产生,因为这实际上是一个问题,并不特定于NodeJS等)
我正在通过身份验证实现REST API服务器,并且已经成功实现了JWT令牌处理,以便用户可以使用用户名/密码通过/ login端点登录,然后从服务器机密生成JWT令牌并将其返回给客户。然后,在每个经过身份验证的API请求中,将令牌从客户端传递到服务器,然后使用服务器机密来验证令牌。
但是,我试图了解关于如何以及在多大程度上验证令牌的最佳实践,以构成一个真正安全的系统。“验证”令牌应该包含什么内容?可以使用服务器秘密来验证签名是否足够,还是我还应该对照服务器中存储的某些数据来交叉检查令牌和/或令牌有效载荷?
基于令牌的身份验证系统仅与在每个请求中传递用户名/密码一样安全,只要获取令牌比获取用户密码同等或更困难。但是,在我看到的示例中,生成令牌所需的唯一信息是用户名和服务器端机密。这不是说,假设一分钟内恶意用户获得了服务器机密知识,他现在就可以代表任何用户产生令牌,从而不仅可以访问一个给定的用户,而且如果密码为获得,但实际上是所有用户帐户?
这使我想到了以下问题:
1)JWT令牌验证是否应仅限于验证令牌本身的签名,仅依靠服务器机密的完整性或通过单独的验证机制进行验证?
在某些情况下,我已经看到了令牌和服务器会话的组合使用,其中在通过/ login端点成功登录后会建立一个会话。API请求会验证令牌,还将令牌中找到的解码数据与会话中存储的某些数据进行比较。但是,使用会话意味着使用cookie,从某种意义上说,它违反了使用基于令牌的方法的目的。这也可能给某些客户带来麻烦。
可以想象服务器将当前所有令牌都保留在内存缓存或类似的内存中,以确保即使服务器机密受到威胁,攻击者也可以生成“有效”令牌,只有通过/ login端点生成的确切令牌将被接受。这是合理的还是仅仅是多余/过度的?
2)如果JWT签名验证是验证令牌的唯一方法,这意味着服务器密钥的完整性是切入点,那么应该如何管理服务器密钥?从环境变量读取并为每个部署的堆栈创建一次(随机化?)?定期更新或轮换(如果这样,如何处理在轮换之前创建但在轮换之后需要验证的现有有效令牌,如果服务器在任何给定时间保留当前和先前的机密就足够了) ?还有吗
当涉及到服务器机密受到威胁的风险时,我可能只是过于偏执,这当然是一个更普遍的问题,需要在所有加密情况下解决……
RSAPrivateKey privateKey
??