TL; DR
- 您必须验证 JWS在服务器始终签名。
- 客户端签名验证并没有给出太多,除非你有一个特定的情况下有意义不要这样做。
- 您不需要验证JWS令牌的签名来检查客户端中的到期。 (除非你是在加密声明,也就是使用JWE,在这种情况下你需要做类似的事情,因为你需要一个密钥来解密声明)。
- 您不需要验证JWS的签名以检查服务器中的到期日期,但是您应该这样做,因为这样可以确保没有人更改过期日期(否则验证将失败,因为如果索赔更改,则重新计算的签名将有所不同)
- 要读取非加密声明,您只需要解码它们即可。您可以在客户端使用jwt-decode。
我现在意识到,之后令牌已经过期,我的前端仍允许用户请求我的API端点[...]
因此,要实现这个逻辑我想我需要验证JWT令牌客户端
如果我正确理解您,您正在讨论检查JWS是否已在客户端过期。 为了做到这一点,您不需要验证令牌签名(尽管您正在使用的库似乎正在为您做both things at the same time,但也可以让您使用ignoreExpiration
标志禁用到期控制)。 (除非您正在加密声明,也就是使用JWE) RFC 7515 (JWS)没有提到过期。Message Signature or MAC Validation不控制到期(并且不应该因为签名给你真实性和完整性)。 即使RFC 7519 (JWT)也不能控制如果JWT is valid or not已解决的到期索赔。
另外,所有的claims are optional。因此,您可以检查JWT是否已过期或未验证签名,因此既不需要公共密钥(用于RSA等非对称加密),也不需要用于对称加密(如AES)的密钥(既不需要公钥也不需要)。 在JWT和JWS令牌中,声明只是明文base64编码,因此您只需decode the payload without verifying if the signature is valid并阅读到期声明。 如果你正在加密有效载荷(又名使用JWE),那么你将无法做到这一点。
的说明从jjwt library
JWTs可以是加密签署(使其成为一个JWS)或加密(使其成为一个JWE)。
Here是从auth0一个ligthweigth库以JWT/JWS的base64encoded声明令牌解码。 一个男人甚至问起checking expiration。
我不知道你为什么认为你应该做这个控制客户端,唯一的好处是避免发送客户端知道会失败的API请求。并且他们应该失败,因为服务器应该验证令牌未过期,以前的签名验证(带有秘密/私钥)显然。
的RFC 7519说了解这个要求:
的“EXP”(到期时间)根据权利要求标识过期时间上 或在此之后,JWT 必须不用于处理被接受。
在一个Web应用程序中,您说的令牌的使用是允许无状态服务器对客户端请求进行身份验证。 可选到期声明的目标是允许服务器对生成的JWS进行一些控制(如果我们使用JWT进行身份验证,则必须签署它们,因此我们应该谈论JWS)。
没有到期,令牌将永久生效或直到用于签名的密钥更改(这将使验证过程失败)。 顺便说一下,invalidatingsessions是使用无状态身份验证最臭名昭着的缺点之一。
如果我们在用于授权的JWS有效负载(又名声明)中包含信息(例如用户拥有哪些角色),则会话失效成为一个实际问题。
从Stop using JWT for sessions
,但更严重的是,它也可以指人与管理员的角色令牌,即使你只是吊销了其管理角色。因为你也不能无效令牌,有没有办法为你免除他们的管理员权限
到期控制的不解决这个问题,我认为是更注重以避免会话劫持或CSRF攻击。
使用CSRF的攻击者将能够使用过期的JWS向您的API发出请求,以跳过到期控制。
另一个问题是使用公钥或密钥验证客户端中的签名。
关于你的问题
我使用似乎都需要一个公共密钥使用它来验证()函数。我似乎没有公钥,只有一个秘密,我只是编了一个秘密,所以它不是用一对产生的。
您指出的验证方法明确指出它接受公钥或密钥。
jwt.verify(token, secretOrPublicKey, [options, callback])
secretOrPublicKey是RSA和ECDSA
字符串或它可以包含HMAC算法的秘密,或PEM缓冲编码的公共密钥我假设你既没有使用,你使用的是像'shhhh'字符串。
var token = jwt.sign({ data: '¿Donde esta Santiago?'}, 'shhhh');
那么你应该做的
var decoded = jwt.verify(token, 'shhhhh');
然而,这里的问题是:是否真的需要客户端签名验证?
我想不是,至少不是这种类型的应用程序,其中客户端只是使用JWS发送后续请求到服务器说:“嘿服务器,我是加百列,我在这里有一个纸张(令牌)这可以保证你的文件是由你签署的。“ 因此,如果客户端不验证JWS并且MITM已成功向该客户端发送了由他自己签名的JWS(而不是由服务器签名的JWS),则后续请求将会失败。 像到期控制一样,签名验证只能防止客户端发出失败的请求。
现在,客户端验证需要发送公钥或密钥。 发送公钥并不代表安全问题,但它是额外的努力和处理,没有什么好处。
发送密钥(如'shhhh')可能代表安全问题,因为是用于签署令牌的相同密钥。