AWS Serverless部署的NestJS应用中带Authorization头的受保护端点无法访问
这种CloudFront返回的403错误,大概率和请求头的传递链路或者边缘服务配置有关,结合你给出的代码和现象,我给你几个具体的排查方向:
1. 先排查API Gateway与Serverless的CORS配置
你的serverless.yaml里虽然配置了允许Authorization头,但有时候Serverless框架自动生成的API Gateway配置会有遗漏,或者CloudFront会过滤掉部分头。可以先做这两个调整:
- 先放宽CORS的headers配置,测试是否能解决问题:
cors: origin: "*" headers: - Content-Type - Authorization - X-Amz-Date - X-Api-Key - X-Amz-Security-Token allowCredentials: true - 登录AWS控制台的API Gateway,找到你的API,检查对应受保护资源的
OPTIONS方法集成响应,确认Access-Control-Allow-Headers里明确包含Authorization。有时候自动生成的配置会漏掉这个,需要手动添加。
2. 确认Authorization头是否真的传到了NestJS
有可能头在传递到Lambda之前就被拦截了,你可以在受保护的控制器里加个日志,看看请求头到底有没有传进来:
import { Controller, Get, Request, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Controller('protected') export class ProtectedController { @Get() @UseGuards(AuthGuard('jwt')) getProtectedContent(@Request() req) { // 打印请求头到CloudWatch日志 console.log('Received Request Headers:', req.headers); return { data: 'Protected content' }; } }
部署后调用受保护端点,然后去CloudWatch里查看Lambda的日志。如果日志里找不到authorization头,说明问题出在API Gateway或CloudFront的转发配置上;如果能看到,那就是NestJS的AuthGuard逻辑有问题,比如token解析错误、密钥不匹配等。
3. 检查CloudFront的Origin Request Policy
从错误信息看你用到了CloudFront,而默认情况下CloudFront不会把Authorization这类敏感头转发到源站(也就是你的API Gateway)。你需要调整CloudFront的行为配置:
- 进入AWS控制台的CloudFront服务,找到你的分发
- 切换到「Behaviors」标签,选中对应的行为规则点击「Edit」
- 在「Origin Request Policy」下拉菜单中,选择一个包含
Authorization头的预定义策略(比如「AllViewerExceptHostHeader」),或者新建一个自定义策略,把Authorization添加到允许转发的Headers列表里 - 保存配置,等待CloudFront完成部署(大概10-15分钟)后再测试
4. 测试OPTIONS预请求是否正常
CORS的预请求(OPTIONS方法)如果没有正确返回允许的头,浏览器会阻止后续的实际请求。你可以用curl直接测试:
curl -X OPTIONS -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: Authorization" -v https://你的API域名/受保护端点路径
查看返回的响应头里是否包含Access-Control-Allow-Headers: Authorization,如果没有,说明API Gateway的CORS配置需要调整。
最后兜底排查:Lambda执行角色权限
虽然你能正常获取JWT,但如果你的AuthGuard需要调用AWS服务(比如Cognito验证token),要确保Lambda的执行角色有对应的权限。不过这个概率比较低,可以放在最后排查。
按这个顺序排查,应该能很快定位到问题所在。
备注:内容来源于stack exchange,提问作者Maurizio Bellemo

