我已经创建了一个 Auth0 客户端,我正在登录并接收此令牌:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik1rVkdOa1l5T1VaQ1JqTkRSVE5EUmtNeU5rVkROMEUyUTBVMFJrVXdPVEZEUkVVNU5UQXpOZyJ9.eyJpc3MiOiJodHRwczovL3RvdGFsY29tbW56LmF1LmF1dGgwLmNvbS8iLCJzdWIiOiJnb29nbGUtb2F1dGgyfDEwMzI5NzA4OTYyMTk5NjUwMjY2MiIsImF1ZCI6ImxTWUtXMUZZdENkMWJLQmdXRWN0MWpCbmtDU3R2dW5SIiwiaWF0IjoxNTA5ODYyMTI1LCJleHAiOjE1MTAyMjIxMjV9.kjmckPxLJ4H9R11XiBBxSNZEvQFVEIgAY_jj2LBy4sEJozBB8ujGE7sq9vEIjMms-Lv2q9WzFQPrqcxyBcYC4Je4QojMgvqLDCodtpot0QUle8QfGmonc1vZYIZyX-wqyOXtRqhoZVEKTeLhm9Le2CV4_a3BwgjkE1LjcDx01GZfsnaId8mh10kGk-DBmr5aVc8MxglLCq5Uk8Zbl2vDc__UMDgx1eQPQg-zve4fUf8zHcxizypYTnF_v0dEAT00L2j5J41SFYdWvP6ReQ3vhVYew2o9iM6u1s75HE-xW8s4pzV4BZAQtgfgIeCd6aVGZs76bcnQXBLej1B7zaPBvA
我现在想做的是使用 jsonwebtoken 验证令牌。该令牌使用 RS256 算法进行签名。
我将签名证书下载为
.pem
,并且我成功使用它来验证令牌,如下所示:
var cert = fs.readFileSync('certificate.pem');
jwt.verify(token, cert, {algorithm: 'RS256'}, (err, decoded) => {
console.log(err)
console.log(decoded)
});
我想做但不起作用的是使用密钥验证令牌(在 Auth0 客户端设置中称为 Client Secret 并且是一个字符串)。
jwt.verify(token, MYSECRET, {algorithm: 'RS256'}, (err, decoded) => {
console.log(err)
console.log(decoded)
});
此代码总是抛出错误:
{ JsonWebTokenError: invalid algorithm
at Object.module.exports [as verify] (C:\code\aws\learn-authorizer\node_modules\jsonwebtoken\verify.js:90:17)
at Object.<anonymous> (C:\code\aws\learn-authorizer\testme.js:25:5)
at Module._compile (module.js:624:30)
at Object.Module._extensions..js (module.js:635:10)
at Module.load (module.js:545:32)
at tryModuleLoad (module.js:508:12)
at Function.Module._load (module.js:500:3)
at Function.Module.runMain (module.js:665:10)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:608:3 name: 'JsonWebTokenError', message: 'invalid algorithm' }
我的问题是:如何使用密钥而不是使用证书文件来验证 RS256 令牌? (我也尝试创建一个使用 HS256 算法的新客户端,但我得到了同样的错误)。
如果您仅使用密钥,则使用 RS256 将不起作用,因为它基于私钥/公钥对。仅使用密钥通常表示 H256。在我的回答中,我假设你所说的 MYSECRET
只是
certificate.pem
的内容。无论如何,我假设你的字符串必须包含
-----BEGIN RSA PRIVATE KEY-----
和
-----END RSA PRIVATE KEY-----
或PUBLIC
而不是 PRIVATE。 您可以在
来源中看到这一点。错误消息中提到的行包含:
if (!~options.algorithms.indexOf(header.alg)) {
return done(new JsonWebTokenError('invalid algorithm'));
}
和
options.algorithms
定义为
if (!options.algorithms) {
options.algorithms = ~secretOrPublicKey.toString().indexOf('BEGIN CERTIFICATE') ||
~secretOrPublicKey.toString().indexOf('BEGIN PUBLIC KEY') ?
[ 'RS256','RS384','RS512','ES256','ES384','ES512' ] :
~secretOrPublicKey.toString().indexOf('BEGIN RSA PUBLIC KEY') ?
[ 'RS256','RS384','RS512' ] :
[ 'HS256','HS384','HS512' ];
}
如果您在开始和结束时没有 RSA 东西,它将寻找以下算法:
'HS256','HS384','HS512'
。
我之前没有将RS256与JWT一起使用过,但我已经将其与ssh一起使用过,并且我知道它对具有标头非常敏感。该字符串的格式必须完全正确。
{algorithm: 'RS256'} to ==>{algorithms: 'RS256'}
并确保为算法写下正确的名称,它会正常工作
根据 Auth0 文档
https://auth0.com/docs/api-auth/tutorials/verify-access-token#verify-the-signature
For HS256, the API's Signing Secret is used. You can find this information at your API's Settings. Note that the field is only displayed for APIs that use HS256.
For RS256, the tenant's JSON Web Key Set (JWKS) is used. Your tenant's JWKS is https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json.
:
decode 能够让我们了解 JWT:
我们解码令牌(使用
const verifyJWT = async (token, verifyURL) => {
return new Promise(async (resolve, reject) => {
const result = jwt.decode(token, { complete: true });
const domainFromToken = result?.payload?.iss;
const signatureUrl = verifyURL ? verifyURL : `${domainFromToken}.well-known/jwks.json`;
const jwksResponse = await axios.get(signatureUrl).catch((exp)=>{
console.log('Error getting jwkResponse:', exp);
reject(false)
});
const jwks = jwksResponse?.data?.keys;
console.log('# of JWKS:', jwks.length, ' -trying to find:', result?.header?.kid);
const relevantKey = jwks.filter(jk => jk.kid === result?.header?.kid)[0];
console.log('relevantKey:', relevantKey);
const algoForImport = selectedKey.alg
const publicKey = await jose.importJWK(relevantKey, algoForImport);
const { payload, protectedHeader } = await jose.jwtVerify(token, publicKey, {
iss: 'issuer, get this from decoded token, or the issuer you expect',
}).catch(exp => {
console.log('exp:', exp);
reject(exp);
});
if (payload && Object.keys(payload).length > 0) {
console.log('Object.keys(payload):', Object.keys(payload));
// uncomment to take a closer look
// console.log('joseResult:', joseResult);
resolve('ok');
}
})
}