智威汤逊validation客户端?

我有一个angular度前端的nodejs api。 API成功使用JWT和护照来保护它的端点。

我现在意识到,在令牌过期之后,我的前端仍然允许用户请求我的api端点,而不会提示他们重新input他们的详细信息以获取新的令牌。

这是我的后端如何生成令牌:

function generateToken(user) { return jwt.sign(user, secret, { expiresIn: 10080 // in seconds }); } 

所以要实现这个逻辑,我想我需要validationJWT令牌客户端。 Q1,这是一个明智的做法。

Q2,我正在使用的JWT库似乎需要一个公钥才能使用它的verify()函数。 我似乎没有一个公钥,只有一个秘密,我只是编了一个秘密,所以它不是由一对产生的。 我的公钥来自哪里,或者是否有另一种validation我的令牌的方式?

这一切似乎应该是显而易见的,我已经错过了一些东西,所以如果这是一个愚蠢的问题,我很抱歉,但我似乎无法find答案?

答案1 :在客户端validation身份validation令牌不被认为是一种好方法,因为它在编码/解码时涉及密钥,并且将密钥保留在客户端并不安全

创build令牌

jwt.sign({ data: 'foobar' }, 'secret', { expiresIn: 60 * 60 });

validation令牌

jwt.verify(token, 'secret', function(err, decoded) { console.log(decoded.foo) // bar });

答案2 :JWT在编码和解码令牌时涉及秘密OR公钥。 它必须被声明或保存在服务器端的configuration文件中。

解释: 解码意味着从Base64解码,在这个过程中没有秘密密钥。 另一方面,validation智威汤逊将需要一个秘密密钥,因为它将涉及encryption签名操作。

总之,解码不需要秘密(记住解码只是解释base64),validation/签名确实需要它

我认为在客户端validationJWT令牌不是一个好主意。 IMO;

1-每当用户login生成访问刷新令牌并返回给用户那样的;

 { "accessToken": <<accessToken>> "refreshToken": <<refreshToken>> "expiresAt": <<expiresAt>> } 

所以你的客户端可以理解访问令牌何时到期,并且可以用刷新令牌刷新它。

2-encryption您放入访问令牌的数据,因为有机会访问没有密钥的数据。 但是有人需要密钥来validation。

Q1:客户端上的令牌validation是一个坏主意。 你可以做的是在客户端上保存一个具有相同过期date的令牌,然后刷新/删除令牌。 但是我认为最好在服务器端有一些date校验存在简单的规则: 不要相信客户端,因为它总是可以发送恶意代码。

Q2: JWT不需要任何公钥。 它总是必须有私钥存储在服务器端的原因,如果有人知道你的秘密密钥你的令牌没有任何意义。 你只能添加一些有效载荷来做更复杂的事情。

TL; DR

  1. 您必须始终服务器上 validation JWS的签名。
  2. 客户端的签名validation并没有太多的提示,除非你有一个特定的情况下才有意义。
  3. 无需validationJWS令牌的签名即可在客户端中检查到期date。 (除非你使用JWEencryption声明,在这种情况下,你需要做类似的事情,因为你需要一个密钥来解密声明)。
  4. 您不需要validationJWS的签名来检查服务器中的到期date,但是您应该这样做,因为这样可以确保没有人更改过期(否则validation将失败,因为如果索赔更改,则重新计算的签名会有所不同)
  5. 要读取非encryption的声明,你只需要解码它们。 你可以在客户端使用jwt-decode 。

我现在意识到,在令牌过期后,我的前端仍然会允许用户请求我的api端点[…]

所以要实现这个逻辑,我想我需要validationJWT令牌客户端

如果我正确地理解了你,你正在谈论检查JWS是否在客户端过期。 为了做到这一点,你不需要validation令牌签名(虽然你正在使用的库似乎是同时为你做两件事情 ,但也可以让你用ignoreExpiration标志禁用到期控制)。 (除非你使用JWEencryption这个声明) RFC 7515(JWS)没有提到过期。 消息签名或MACvalidation不控制到期(并且不应该因为签名给你真实性和完整性)。 即使RFC 7519(JWT)也不控制JWT 有效或无效的到期请求。

而且,所有的声明都是可选的 。

因此,您可以检查JWT是否已经过期而没有validation签名,因此您不需要公钥(对于RSA等非对称encryption)或密钥(对于AES等对称encryption)。 在JWT和JWS令牌中,声明只是明文base64编码,所以您可以在不validation签名是否有效的情况下解码有效负载并读取到期声明。 如果你正在encryption有效载荷(又名使用JWE),那么你将无法做到这一点。

来自jjwt库的一个注释

智威汤逊可以encryption签名 (使其成为JWS )或encryption (使其成为JWE )。

这是一个来自auth0ligthweig库,用于解码JWT / JWS令牌的base64编码声明 。 一个人甚至要求检查过期 。

我不知道为什么你认为你应该做这个控制客户端,唯一的好处是避免发送客户端知道会失败的API请求。 他们应该失败,因为服务器应该validation令牌没有过期,以前的签名validation(与秘密/私钥)显然。

RFC 7519说这个说法:

“exp”(到期时间)声明标识JWT 不得接受处理的期满或过期时间。

在一个Web应用程序中,像你说的使用标记就是允许无状态的服务器来validation客户端的请求。 可选到期声明的目标是允许服务器对生成的JWS进行一些控制(如果我们正在使用JWT进行身份validation,那么签名是必须的,所以我们应该谈论JWS)。

如果没有到期,令牌将永远有效,或直到用于签名的密钥更改(这将使validation过程失败)。 顺便说一下, 无效 会话是使用无状态身份validation最臭名昭着的缺点之一。

如果我们在用于授权的JWS有效载荷(又名声明)中包含信息(例如用户拥有哪些angular色),则会话失效成为一个真正的问题。

从停止使用智威汤逊会议

但更严重的是,这也可能意味着某人拥有一个具有pipe理员angular色的令牌,即使您刚刚撤消了其pipe理员angular色。 由于您无法使令牌失效,因此您无法删除其pipe理员访问权限

到期控制并没有解决这个问题,我认为更多的是为了避免会话劫持或CSRF攻击。

使用CSRF的攻击者将能够使用过期的JWS向您的API请求跳过到期控制。

另一个问题是使用公钥或密钥来validation客户端中的签名。

关于你的问题

我使用似乎需要一个公共密钥来使用它的verify()函数。 我似乎没有一个公钥,只有一个秘密,我只是编了一个秘密,所以它不是由一对产生的。

你指出的validation方法明确地说,它接受一个公钥或密钥。

 jwt.verify(token, secretOrPublicKey, [options, callback]) 

secretOrPublicKey是一个string或缓冲区,包含HMACalgorithm的秘密,或者RSA和ECDSA的PEM编码公钥

我假设你既没有使用,也没有使用'shhhh'这样的string。

 var token = jwt.sign({ data: '¿Donde esta Santiago?'}, 'shhhh'); 

那你应该这样做

 var decoded = jwt.verify(token, 'shhhhh'); 

但是,这里的问题是:客户端签名validation真的需要吗?

我认为不是,至less不是这种应用程序,客户端只是使用JWS向服务器发送后续请求,说:“嘿,服务器,我是加百利,我有一个纸(令牌),以确保那张纸是由你签署的。“ 因此,如果客户端没有validationJWS,并且MITM已经成功地向该客户端发送了由他自己签名的JWS(而不是由服务器签名的JWS),则后续请求将会失败。 像过期控制一样,签名validation只能防止客户端发出失败的请求。

现在,客户端validation需要发送公共密钥或密钥。 发送公共密钥并不代表安全问题,但它是额外的努力和处理,没有什么好处。

发送秘密密钥(如“shhhh”)可能代表安全问题,因为是用于签署令牌的相同密钥。