API Gateway触发Lambda时RequestContext缺失Cognito Authorizer问题
以下是逐步排查和解决的步骤:
1. 确认API Gateway授权器配置有效性
- 检查目标API资源/方法绑定的授权器类型为Cognito用户池授权器,而非IAM或自定义授权器
- 验证授权器的
Token Source设置为Authorization,与前端传递的请求头字段一致 - 在API Gateway控制台的授权器页面点击「测试」,输入有效的ID Token,确认能返回包含自定义属性的claims,排除授权器本身的故障
2. 验证前端Token传递正确性
- 确认前端请求头的
Authorization字段格式为Bearer <ID_TOKEN>,必须包含Bearer前缀(API Gateway默认要求此格式,缺少会导致授权失败) - 本地解码ID Token(可使用JWT库或离线工具),检查Token是否有效(未过期、签名正确),且包含预期的自定义用户属性
- 通过浏览器开发者工具抓包,确认请求确实携带了正确的
Authorization头
3. 检查API Gateway部署状态
- 授权器配置或资源绑定变更后,必须重新部署API到对应阶段,否则新配置不会生效
- 确认当前调用的API endpoint指向的是最新部署的阶段
4. 核实Lambda集成类型与事件结构
- 如果使用Lambda Proxy集成(Amplify创建的API默认采用此模式),用户授权信息应在
event.requestContext.authorizer.claims路径下;若未找到,检查是否误写为req.apiGateway.event(正确的Lambda事件参数直接是event,无需req.apiGateway前缀,除非你用了框架封装) - 如果是非Proxy集成,需在API Gateway的「集成请求」中配置映射模板,将
$context.authorizer.claims映射到Lambda的输入参数(比如请求体或查询参数)
5. 检查Cognito用户池与应用客户端配置
- 确认应用客户端的「Allowed OAuth Scopes」包含
openid(生成ID Token必须的scope) - 自定义用户属性需在创建时勾选「Include in ID token」,或在用户池的「App client settings」中,将该属性添加到ID Token的返回字段列表中
6. 排查授权相关权限与日志
- 检查API Gateway的执行角色是否拥有
cognito-idp:VerifyToken和cognito-idp:GetUser权限,确保能正常验证Token并获取用户信息 - 开启API Gateway的访问日志,查看CloudWatch中是否有授权失败的记录(如Token无效、权限不足等)
备选方案:直接在Lambda中解析ID Token
如果以上排查仍未解决,可直接从请求头中提取Token,手动验证并解码:
// Node.js示例 const jwt = require('jsonwebtoken'); const jwksClient = require('jwks-rsa'); const client = jwksClient({ jwksUri: 'https://cognito-idp.<region>.amazonaws.com/<userPoolId>/.well-known/jwks.json' }); function getKey(header, callback) { client.getSigningKey(header.kid, function(err, key) { const signingKey = key.getPublicKey(); callback(null, signingKey); }); } exports.handler = async (event) => { const authHeader = event.headers.Authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return { statusCode: 401, body: 'Unauthorized' }; } const token = authHeader.split(' ')[1]; return new Promise((resolve, reject) => { jwt.verify(token, getKey, { audience: '<appClientId>' }, (err, decoded) => { if (err) reject({ statusCode: 401, body: 'Invalid token' }); // decoded中包含用户所有claims,包括自定义属性 resolve({ statusCode: 200, body: JSON.stringify(decoded) }); }); }); };
内容的提问来源于stack exchange,提问作者RupturingFarms
相关产品推荐
相关产品推荐

