为啥这个经过验证的 JSON Web Token (JWT) 输出未定义?
Posted
技术标签:
【中文标题】为啥这个经过验证的 JSON Web Token (JWT) 输出未定义?【英文标题】:Why does this verified JSON Web Token (JWT) output as undefined?为什么这个经过验证的 JSON Web Token (JWT) 输出未定义? 【发布时间】:2021-06-03 20:49:26 【问题描述】:我正在尝试使用 jwks-rsa 和 jsonwebtoken 解码 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();
那么如何让它返回正确解码的令牌?
【问题讨论】:
【参考方案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);
【讨论】:
以上是关于为啥这个经过验证的 JSON Web Token (JWT) 输出未定义?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 JSON Web Token (JWT) 在不知道密钥的情况下解密
使用 REST 和 JSON Web Token 上传/下载文件
使用 JSON Web Token (JWT) 进行身份验证和授权