如何在Python 3.6中验证AWS Cognito生成的JWT签名?
解决Cognito JWT "Signature verification failed" 问题的排查步骤
我之前也碰到过一模一样的问题,折腾了好一阵子才搞定,给你梳理几个最容易踩的坑和验证步骤:
确认公钥匹配且来源正确
Cognito的签名公钥需要从对应用户池的JWKS端点获取:https://cognito-idp.<region>.amazonaws.com/<userPoolId>/.well-known/jwks.json。你必须确保使用的公钥与JWT头部kid字段完全匹配——很多人要么拿错了其他用户池的公钥,要么没匹配kid直接用了第一个公钥,这会直接导致签名验证失败。检查JWT的核心字段合法性
先解码JWT看看关键字段是否正确:iss必须严格等于你的用户池URL:https://cognito-idp.<region>.amazonaws.com/<userPoolId>,大小写、区域、用户池ID都不能错;- 确保令牌没有被截断、篡改,是完整的
header.payload.signature三段式结构。你可以用jwt decode <your-token>命令(比如jwt-cli工具)快速解析验证。
验证算法是否匹配
Cognito默认使用RS256非对称加密算法,你的验证脚本必须明确指定用RS256,绝对不能用HS256(对称加密)。很多新手会不小心写错算法参数,这是高频错误点。处理公钥格式问题
JWKS返回的公钥是Base64编码的原始字符串,你需要把它转换成标准的PEM格式才能用于验证:- 添加
-----BEGIN PUBLIC KEY-----开头和-----END PUBLIC KEY-----结尾; - 每64个字符换行一次。
如果直接用原始Base64字符串验证,大概率会失败。
- 添加
排除令牌过期干扰
虽然错误提示是签名失败,但有时候过期的令牌也会触发类似报错,先确认exp字段的时间是否在当前时间之后。
举个正确验证的示例(Node.js)
用jsonwebtoken和jwks-rsa库可以自动处理公钥获取和格式转换,避免手动踩坑:
const jwt = require('jsonwebtoken'); const jwksClient = require('jwks-rsa'); // 替换成你的用户池信息 const userPoolRegion = 'us-east-1'; const userPoolId = 'your-user-pool-id'; const client = jwksClient({ jwksUri: `https://cognito-idp.${userPoolRegion}.amazonaws.com/${userPoolId}/.well-known/jwks.json` }); function getSigningKey(header, callback) { client.getSigningKey(header.kid, (err, key) => { const signingKey = key.getPublicKey(); callback(null, signingKey); }); } // 替换成你的JWT令牌 const token = 'your-jwt-token-here'; jwt.verify( token, getSigningKey, { algorithms: ['RS256'], issuer: `https://cognito-idp.${userPoolRegion}.amazonaws.com/${userPoolId}` }, (err, decoded) => { if (err) { console.error('验证失败原因:', err.message); return; } console.log('验证成功,解码内容:', decoded); } );
如果这些步骤都排查过还是有问题,可以把解码后的JWT头部和payload(敏感信息打码)贴出来,方便进一步定位问题。
内容的提问来源于stack exchange,提问作者KyelJmD
相关产品推荐
相关产品推荐

