【问题标题】:Why does this verified JSON Web Token (JWT) output as undefined?为什么这个经过验证的 JSON Web Token (JWT) 输出未定义?
【发布时间】:2021-06-03 20:49:26
【问题描述】:

我正在尝试使用 jwks-rsajsonwebtoken 解码 JWT id_token,但结果返回为 undefined

我知道这与回调有关,而且我需要等待来自 getKey 函数的响应,但我不知道如何构建代码来实现这一点。

这就是我目前所拥有的......

function do_thing(properties, context) {

  const id_token = "REDACTED";

  // Verify using getKey callback
  var jwksClient = require('jwks-rsa');
  var client = jwksClient({
    jwksUri: 'https://REDACTED.com/.well-known/jwks.json'
  });

  function getKey(header, callback) {
    client.getSigningKey(header.kid, function(err, key) {
      var signingKey = key.publicKey || key.rsaPublicKey;
      callback(null, signingKey);
    });
  }

  var jwt = require('jsonwebtoken');
  jwt.verify(id_token, getKey, { algorithms: ['RS256'] }, function(err, decoded) {
    if (err) {
      console.log(err);
    } else {
      return decoded;
    }
  });
const bubble_obj = do_thing();
console.log(bubble_obj); //This is `undefined`

console.log(bubble_obj); 输出为undefined

我知道上述代码的问题是由于回调和异步代码的性质,因为如果我将 console.log 移动到 jwt.verify 调用中,它将显示正确解码的令牌。

查看这里的例子...

function do_thing(properties, context) {

  const id_token = "REDACTED";

  // Verify using getKey callback
  var jwksClient = require('jwks-rsa');
  var client = jwksClient({
    jwksUri: 'https://REDACTED.com/.well-known/jwks.json'
  });

  function getKey(header, callback) {
    client.getSigningKey(header.kid, function(err, key) {
      var signingKey = key.publicKey || key.rsaPublicKey;
      callback(null, signingKey);
    });
  }

  var jwt = require('jsonwebtoken');
  jwt.verify(id_token, getKey, { algorithms: ['RS256'] }, function(err, decoded) {
    if (err) {
      console.log(err);
    } else {
      console.log(decoded); //When moved here, it prints the correctly decoded token
      return decoded;
    }
  });
const bubble_obj = do_thing();

那么如何让它返回正确解码的令牌?

【问题讨论】:

    标签: javascript node.js jwt


    【解决方案1】:

    您没有正确处理异步代码。 jwt.verify 方法返回一个 Promise 如果你不传递回调方法。

    如果您在do_thing 函数中使用return jwt.verify(id_token, getKey, { algorithms: ['RS256'] }) 并像这样调用它do_thing().then((decodedToken) => console.log(decodedToken)),它应该可以按预期工作。

    【讨论】:

    • 这现在给出了一个错误,说 JsonWebTokenError: verify must be called asynchronous if secret or public key is provided as a callback" 所以我尝试将 do_thing() 函数转换为异步函数并使其成为 return await jwt.verify(id_token, getKey, { algorithms: ['RS256'] }) 但这并没有消除错误。在此处查看工作示例:repl.it/join/fqcsbnck-twistedsizzler
    • 我已经更新了 repl.it 上的代码。它使用 getSigningKey 的异步版本,并在匿名自调用函数中调用 verifyToken 方法
    • 如果您阅读Promises,这真的有助于清除问题。在高层次上,它们允许您使用异步函数而无需传递回调。这使您的代码更加干净和可读。返回Promise 的函数可以与await 一起使用或使用.then()
    【解决方案2】:

    你需要处理 jwt.verify 返回的 promise。要么使用promise.then。或者使用 async/await。

     async function do_thing(properties, context) {
    
      const id_token = "REDACTED";
    
      // Verify using getKey callback
      var jwksClient = require('jwks-rsa');
      var client = jwksClient({
        jwksUri: 'https://REDACTED.com/.well-known/jwks.json'
      });
    
      function getKey(header, callback) {
        client.getSigningKey(header.kid, function(err, key) {
          var signingKey = key.publicKey || key.rsaPublicKey;
          callback(null, signingKey);
        });
      }
    
      const jwt = require('jsonwebtoken');
      return jwt.verify(id_token, getKey, { algorithms: ['RS256'] });
      
    }
    
    const decodedToken = await do_thing();
    console.log("decoded token:", decodedToken);
    

    【讨论】:

    • 这不起作用,因为const decodedToken = await do_thing(); 不在异步函数内。因此它会引发错误。
    • 你必须处理你的调用函数才能让它工作。
    【解决方案3】:

    您可以使用 Promise 通过 JWK 回调和 Promise 验证 JWT,如下所示。您需要将以下内容包装在 async 函数中以使用 verify_jwks() 函数的结果:

    const token = "REDACTED";
    var jwksClient = require('jwks-rsa');
    
    // Creates a JWKS Client with a rate limit that
    // limits the number of calls to our JWKS endpoint
    var client = new JwksClient({
        jwksUri: 'https://REDACTED.com/.well-known/jwks.json',
        rateLimit: true,
        jwksRequestsPerMinute: 10, // Default Value
        cache: true, // Default Value
        cacheMaxEntries: 5, // Default value
        cacheMaxAge: 600000, // Defaults to 10m
    });
    
    // Verifies the JWKS asynchronously, returns Promise
    async function verify_jwks() {
        function getKey(header, callback) {
            // Callback that returns the key the corresponding key[kid]
            client.getSigningKey(header.kid, function(err, key) {
                const signingKey = key.getPublicKey() || key.publicKey || key.rsaPublicKey;
                callback(null, signingKey);
            });
        }
    
        // Returns a Promise with verification result or error
        return new Promise((resolve,reject) =>
            jsonwebtoken.verify(token,getKey, {
                algorithms: ["HS256", "RS256"]
            },
            function(err,decoded) {
                return err ? reject(err) : resolve(decoded);
            }
        ));
    }
                
    let result;
    await verify_jwks()
        .then(decoded => result = decoded)
        .catch(error => console.log(error));
    console.log(result);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-19
      • 2016-11-24
      • 2016-04-07
      • 1970-01-01
      • 2017-08-18
      • 2018-02-10
      • 2018-02-12
      • 2019-09-23
      相关资源
      最近更新 更多