(源自这篇文章,因为这确实是一个独立的问题,并不特定于NodeJS等)
我正在实现具有身份验证功能的REST API服务器,已成功实现JWT token处理,以便用户可以通过/login端点使用用户名/密码登录,然后从服务器密钥生成JWT token并返回给客户端。然后,客户端将令牌传递到每个经过身份验证的API请求中的服务器,然后使用服务器密钥验证令牌。
但是,我正在尝试了解确切的最佳实践,以及以何种程度验证令牌才能使系统真正安全。 "验证"令牌需要哪些步骤?仅使用服务器密钥验证签名是否正确是否足够,还是还应该将令牌和/或令牌有效负载与存储在服务器上的某些数据进行交叉检查?
令牌身份验证系统只有与每个请求中传递用户名/密码一样安全,前提是获得令牌与获得用户密码同样困难或更困难。然而,在我看到的示例中,生成令牌所需的唯一信息是用户名和服务器端密钥。这是否意味着假设恶意用户获得服务器密钥的知识,他现在可以代表任何用户生成令牌,从而不仅具有一个给定用户的访问权限(如果获得密码将是事实),但实际上具有所有用户帐户的访问权限?
这就引出了以下问题:
1)JWT token验证是否应限于仅验证令牌本身的签名,并依赖于仅服务器密钥的完整性,还是应该使用单独的验证机制?
在某些情况下,我看到令牌和服务器会话的组合使用,在/login端点成功登录后建立会话。 API请求验证令牌,并将令牌中找到的解码数据与存储在会话中的某些数据进行比较。但是,使用会话意味着使用cookie,从某种意义上讲,它会使令牌基础方法的使用变得毫无意义。它还可能会对某些客户端造成问题。
有人可以想象服务器将当前所有使用的令牌存储在memcache或类似系统中,以确保即使服务器密钥被攻击者泄露从而生成“有效”令牌,也只会接受通过/login端点生成的完全相同的令牌。这是合理的还是多余的/过度的?
2) 如果JWT签名验证是验证令牌的唯一方式,意味着服务器密钥的完整性是破解的关键点,那么应该如何管理服务器密钥?从环境变量中读取并在每个部署堆栈中创建(随机化)一次?定期更新或轮换(如果是这样,如何处理在轮换之前创建但需要在轮换后进行验证的现有有效令牌,也许在任何时候服务器保存当前和上一个密钥就足够了)?还是其他方式?
也许我只是在对服务器密钥被攻击者泄露的风险过度担忧,这当然是所有加密情况下必须解决的更一般问题...
RSAPrivateKey privateKey
吗? - kittu