【问题标题】:Validating a JWT in node.js在 node.js 中验证 JWT
【发布时间】:2019-12-09 19:54:21
【问题描述】:

我正在尝试根据此示例(在 .NET 中编写)解析和验证 node.js 中的 JWT 令牌:https://github.com/liveservices/LiveSDK/blob/master/Samples/Asp.net/AuthenticationTokenSample/JsonWebToken.cs

这是我验证令牌的节点 js javascript:

var validateSignature = function(key, claims, envelope, signature) {
    var hasher = crypto.createHash('sha256');
    hasher.update(key + "JWTSig");
    var key = hasher.digest('binary');
    var hmac = crypto.createHmac('sha256', key);
    hmac.update(envelope + '.' + claims);
    var out = hmac.digest('base64');
    console.log(out);
    console.log(signature);
    console.log(out === signature);
}

现在,非常奇怪的是 - 它几乎可以工作。以下是三个 console.log 语句的输出:

pEwNPJ+LUHBdvNx631UzdyVhPFUOvFY8jG3x/cP81FE=
pEwNPJ-LUHBdvNx631UzdyVhPFUOvFY8jG3x_cP81FE
false

在我看来,除了 +-/_= 之外,哈希值都相同

有人发现我的错误吗?与我的 base64 编码有关。

更新

我又玩了一些,这里的 base64 编码似乎有些奇怪。 node js中的如下代码:

console.log(signature);
var b = new Buffer(signature, 'base64');
console.log(b.toString('base64'));

产量:

pEwNPJ-LUHBdvNx631UzdyVhPFUOvFY8jG3x_cP81FE
pEwNPJLUHBdvNx631UzdyVhPFUOvFY8jG3xcP81F

这看起来很奇怪,对吧?

【问题讨论】:

  • 可能是该节点的 hmac 函数输出了一个 Web 或 URL 安全哈希,而您的其余代码是正确的。
  • 类似的东西,我刚刚更新了

标签: javascript authentication node.js base64 jwt


【解决方案1】:

感谢 Timothy Meade 的评论并将我推向正确的方向。

Node 的 Buffer 类型使用 +、/ 和 = 生成标准 Base64

这里提到了一个 URL 安全的 base64 编码:http://en.wikipedia.org/wiki/Base64

它用 - 代替 +,用 _ 代替 /,= 是可选的。在 QueryString (d'uh) 上传递的令牌是 URL 安全版本。因此有区别。

代码被一个简单的修复:

out = out.replace('+','-').replace('/','_').replace('=','');

【讨论】:

  • 一个旧帖子,但仍然。您的代码不会替换所有出现的情况。 out = out.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); 会起作用 :)
  • replace(/=/g, '') 替换所有等号字符,即使它们不在字符串末尾
【解决方案2】:

我前段时间写了这个库,我想你可以使用一些代码。它应该在 node.js 和现代浏览器中运行。

【讨论】:

    【解决方案3】:

    这不是您尝试使用的确切方法,但我相信它是在 NodeJS 中验证 JWT 的首选方法。请注意,我使用 NPM base64url 库在 base64Url(JWT 的默认编码)和 base64(NodeJS 对验证功能的期望)之间进行转换。

    另外请注意,您需要一个公钥和私钥对分别进行签名和验证。我在这篇文章的底部包含了用于签名和验证此 JWT 的私钥和公钥。

    const base64 = require('base64url');
    const crypto = require('crypto');
    const verifyFunction = crypto.createVerify('RSA-SHA256');
    const fs = require('fs');
    
    // The sample JWT from https://jwt.io/
    const JWT = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA';
    
    // This just gets the value of the public key (same as the one at bottom of this post)
    const PUB_KEY = fs.readFileSync(__dirname + '/id_rsa_pub.pem', 'utf8');
    
    // Split the JWT by `.` to get each part
    const jwtHeader = JWT.split('.')[0];
    const jwtPayload = JWT.split('.')[1];
    const jwtSignature = JWT.split('.')[2];
    
    // We only need the first two pieces to verify
    verifyFunction.write(jwtHeader + '.' + jwtPayload);
    verifyFunction.end();
    
    // IMPORTANT: NodeJS expects base64 format, not base64url format!
    const jwtSignatureBase64 = base64.toBase64(jwtSignature);
    
    // IMPORTANT: You need to specify that the `jwtSignatureBase64` data is base64 format, 
    // otherwise, it will default to Buffer format and return false
    const signatureIsValid = verifyFunction.verify(PUB_KEY, jwtSignatureBase64, 'base64');
    
    console.log(signatureIsValid); // true
    

    以下键来自示例 JWT mentioned here

    私钥:

    -----BEGIN RSA PRIVATE KEY-----
    MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWw
    kWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mr
    m/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEi
    NQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV
    3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2
    QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjs
    kFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q+/1bip4Z/x1IVES84/yTaM8p0go
    amMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw+wyXlwaM
    +bclUCrh9e1ltH7IvUrRrQnFJfh+is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9
    D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC
    0Lj9FkWcfmLcpGlSXTO+Ww1L7EGq+PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5Y
    lSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl+zNVKP8w4eBv0vWuJJF+
    hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNp
    bU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X
    +jpoqxj4efZfkUrg5GbSEhf+dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c+GlTc9B
    BwfMr59EzBq/eFMI7+LgXaVUsM/sS4Ry+yeK6SJx/otIMWtDfqxsLD8CPMCRvecC
    2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh4qZtnhKjY4TKDjx
    QYufXSdLAi9v3FxmvchDwOgn4L+PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz
    5pTpPI0OjgWN13Tq8+PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9
    Imf9n2spL/6EDFId+Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0
    NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j
    8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma
    3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5K
    y18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrB
    jg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd+mX7iE=
    -----END RSA PRIVATE KEY-----
    

    公钥:

    -----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv
    vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc
    aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy
    tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0
    e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb
    V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9
    MwIDAQAB
    -----END PUBLIC KEY-----
    

    【讨论】:

      猜你喜欢
      • 2017-08-11
      • 2018-04-19
      • 2021-12-25
      • 2016-11-24
      • 2021-02-09
      • 1970-01-01
      • 2020-11-07
      • 2023-03-12
      • 2018-11-08
      相关资源
      最近更新 更多