You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS中修改AWS Cognito Token一个字符仍验证通过?

为什么修改AWS Cognito JWT的最后一个字符后,node-jose验证仍能通过?

这种情况完全不符合预期——正常来说,修改JWT签名部分的任意字符都应该导致验证失败。出现这个问题大概率是验证逻辑的容错性过强,或者代码中缺少了关键的校验约束,下面是具体分析和解决方案:

问题原因分析

  1. node-jose默认验证逻辑的宽松性
    默认情况下,jose.JWS.createVerify(keystore)会尝试用密钥库中的所有密钥去验证JWT,并且对算法的校验不够严格。如果你的密钥库中有多个密钥,极端情况下可能出现误匹配(虽然概率极低),或者旧版本node-jose存在签名校验的bug。

  2. Base64URL解码的容错机制
    部分Base64URL解码实现会忽略末尾的无效字符,或者对填充字符=的处理过于宽松。但RS256签名是基于哈希的,哪怕一个字节的变化都应该导致验证失败,这个因素的影响相对较小,但值得排查。

  3. 误修改了非签名部分
    如果你误以为修改的是签名段(JWT第三个.之后的内容),但实际改的是payload段,那验证失败才是正常的——但你描述的是修改最后一个字符,大概率是签名段,所以这个可能性较低。

解决方案

1. 明确指定验证的算法和kid

在创建验证器时,强制指定JWT头中声明的算法和kid,避免node-jose尝试无关密钥,同时严格校验算法匹配:

const jose = require('node-jose');

const jwks = { 
  "keys": [ 
    { 
      "alg": "RS256", 
      "e": "AQAB", 
      "kid": "GswyT6a+OAuL5kCrRCmT5xmfCL6uFuo1MWaD+otmfd4=", 
      "kty": "RSA", 
      "n": "hrYesjnwXvwfh8Pr87Jun5uAb3YKF9XNYFbxjQwlvd__8JQw3l0iGJVLjmHKoOHQztVUdeWe9jfkShEA2FjFukb21mPH1UCOYGWg7HR_lJz1IAaYf0ysQXmG1fWkhYDisHGrdEFURbWNhmSzJcqCM9Faa6LBGzUMMJzwDMyrxjOP8nZYbVhjorpFnHOfxUYPJ_RhZfUEXY1F6RbmHdtZ7rpFeaOzptKFfEqOcCU0avkPrpPcrKNaZ4kMN3YOHl-gPzoy-HgjAYYOGE1XMW316t1keEoYJhk8MY9NjriPx7RNcsbPpeRpb7bS2Vki1p8NYhBqywoGv0QYZK_b1JLlAw", 
      "use": "sig" 
    }, 
    { 
      "alg": "RS256", 
      "e": "AQAB", 
      "kid": "IQCV14AYWuTjxjwqbtxW9uh2psd2iyjHox6TQZihdwo=", 
      "kty": "RSA", 
      "n": "ojo3CemQghYpj_Vic-a28BNj69cce76DmVKBr0U7Uj2q0rgfrE0aamUdya21-NJAOq2D5PwqZyxQJOXPhngpOKS9bTaBfeqdTzKrz2b98Q0Q-ADEYNoWRtVMYFDnpeq1Xkjl3X-Y1nB76SD5Xjtv-g3z7VHWD-p91hGZTWotaid1yvGWcjL5VHAFI6Qko0s_-RPlj93BUnIVboWfWjmsC6qcC9lIa4V_562xS7bOMNJDt6UGum0bWUhexhytWyplZnTUfO2Pb4ML2e52zhe3f87jFny9pra9N_ULQwrU8DpslvK-AdmcLYaHNOt1J8g5gS_Es45HDMkkNjwinikiMQ", 
      "use": "sig" 
    } 
  ] 
};

const jwt = 'eyJraWQiOiJJUUNWMTRBWVd1VGp4andxYnR4Vzl1aDJwc2QyaXlqSG94NlRRWmloZHdvPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI0MGMwNTc4My1jMWI2LTRiZWQtYWUzZS1hNWQ2ZWE4NzM2MmIiLCJldmVudF9pZCI6ImRiMWEzMzI2LTY0YjctMTFlOC04MmFjLTU3OWMxZTQ2M2U2MiIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiYXdzLmNvZ25pdG8uc2lnbmluLnVzZXIuYWRtaW4iLCJhdXRoX3RpbWUiOjE1Mjc3NjAxNDUsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC5hcC1zb3V0aGVhc3QtMS5hbWF6b25hd3MuY29tXC9hcC1zb3V0aGVhc3QtMV9jOVZENWdqN3AiLCJleHAiOjE1Mjc3NjM3NDUsImlhdCI6MTUyNzc2MDE0NSwianRpIjoiNGNjZGI4YjAtNjg3MS00NWRiLTkzYjktZmYwODczNTIyMDJhIiwiY2xpZW50X2lkIjoiNm45aDRhdjJibGR2OTM1M21hZWFuaTZuaWoiLCJ1c2VybmFtZSI6ImppZXdtZW5nLmxpbUAyMzU5bWVkaWEuY29tIn0.Kp5ZVTJo-zTb3Tj26UHcjmufVfxtDKKHFgQNnEQOaMUJ8KtPXQPy_gL0ZzUBS4-rn0BsphAD_vT80iLjOxLKa9C-qNm2vq_28zlySnbqh1aN_pOTFC5YkQFrspU6_B_AIC_1GtcFuTlCksBe5AJLaYZhzYaxqy3ubcG2z3Eyzf13OlwHoUqNeJgtKk7Ff48nUF2pAUkCQbkFEhLTcoxh1xjJYcex4yEM2LeW1ZLdlFp2R5YGDB6al-MyMAh03r_SIGAuD-lEnz3rmeR5XUsdIj4Yg5UPAWIGufmb1fPa740iTf-7OF2FF7YLPQW60ng6w_cWGe1e36K3B5RVbduf5A';

// 解析JWT头,获取声明的kid和算法
const getJwtHeader = (token) => {
  const [headerBase64] = token.split('.');
  try {
    const headerString = Buffer.from(headerBase64, 'base64url').toString('utf8');
    return JSON.parse(headerString);
  } catch (err) {
    throw new Error('Invalid JWT header');
  }
};

const jwtHeader = getJwtHeader(jwt);

jose.JWK.asKeyStore(jwks)
  .then(keystore => {
    // 强制指定算法和kid,严格校验
    return jose.JWS.createVerify({
      algorithms: [jwtHeader.alg],
      kid: jwtHeader.kid
    }, keystore).verify(jwt);
  })
  .then(result => {
    console.log('OK!', result.payload.toString('utf8'));
  })
  .catch(err => {
    console.error('Verification failed:', err.message);
  });

2. 升级node-jose到最新版本

旧版本的node-jose可能存在签名校验的bug,执行以下命令升级到最新稳定版:

npm install node-jose@latest

3. 用第三方工具交叉验证

可以用JWT在线验证工具(比如jwt.io)分别验证原始Token和修改后的Token,确认修改后的Token确实应该验证失败,排除代码逻辑外的问题。

内容的提问来源于stack exchange,提问作者Jiew Meng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:54:02