使用Cognito作为授权器的AWS API Gateway遭遇CORS错误求助
使用Cognito作为授权器的AWS API Gateway CORS错误排查与解决
在AWS API Gateway中搭配Cognito授权器时遭遇CORS错误,已尝试调整Method Response、Integration Response、Gateway Responses及Enable CORS配置,均未解决问题。无认证状态下API可正常响应,启用Cognito认证后,请求返回401、403、500等状态码且始终伴随CORS错误,测试请求未触发Lambda执行,通过CDK部署的示例代码可在本地复现该问题。
相关代码示例
Lambda处理代码
import json def handler(event, context): print('Lambda is here') return dict( statusCode=200, headers={ 'Access-Control-Allow-Headers': '*', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': '*', 'Access-Control-Allow-Credentials': 'true', }, body=json.dumps({'message': 'lambda works'}) )
测试用HTML代码
<head> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> </head> <body> <script> axios.get( "api_gateway_url", ) .then(response =>alert(response.data.message)) .catch(error => { console.log(error) alert("ERROR") }) </script> </body>
核心排查与解决步骤
1. 配置Gateway Responses返回CORS头
当Cognito授权失败(返回401/403)时,请求不会到达Lambda,此时CORS头必须由API Gateway的Gateway Responses直接返回。需针对以下错误类型添加CORS配置:
DEFAULT_4XXDEFAULT_5XXUNAUTHORIZED(对应401)ACCESS_DENIED(对应403)
配置需包含:
Access-Control-Allow-Origin: 替换为前端实际域名(不能用*,因为Allow-Credentials: true与*冲突,不被浏览器允许)Access-Control-Allow-Methods: 填写实际允许的请求方法(如GET,POST,OPTIONS)Access-Control-Allow-Headers:Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-TokenAccess-Control-Allow-Credentials:true
2. 修复Lambda的CORS头冲突
Lambda返回的Access-Control-Allow-Origin设置为*,同时启用Allow-Credentials: true违反浏览器CORS规则,需将*替换为前端具体域名(如https://your-frontend-domain.com)。
3. 确保OPTIONS预检请求正常通过
- 给API Gateway的OPTIONS方法设置跳过Cognito认证,否则预检请求会被直接拦截,触发CORS错误。
- 可通过API Gateway的
Enable CORS功能自动配置OPTIONS方法,或手动配置其Integration Response返回正确的CORS头。
4. 校验Cognito授权器配置
- 确认Cognito用户池、客户端ID配置正确,令牌(ID Token/Access Token)的受众(Audience)与API Gateway授权器配置一致。
- 检查前端请求是否正确携带
Authorization头,格式为Bearer <token>。
5. CDK部署时的配置要点
若使用CDK部署,需在代码中明确配置Gateway Responses的CORS头,示例片段:
const api = new apigateway.RestApi(this, 'MyApi', { defaultCorsPreflightOptions: { allowOrigins: apigateway.Cors.ALL_ORIGINS, // 生产环境替换为具体域名 allowMethods: apigateway.Cors.ALL_METHODS, allowHeaders: apigateway.Cors.DEFAULT_HEADERS, allowCredentials: true, }, }); // 针对401错误配置Gateway Response api.addGatewayResponse('UnauthorizedResponse', { type: apigateway.ResponseType.UNAUTHORIZED, statusCode: '401', responseHeaders: { 'Access-Control-Allow-Origin': "'https://your-frontend-domain.com'", 'Access-Control-Allow-Credentials': "'true'", }, }); // 针对403错误配置Gateway Response api.addGatewayResponse('AccessDeniedResponse', { type: apigateway.ResponseType.ACCESS_DENIED, statusCode: '403', responseHeaders: { 'Access-Control-Allow-Origin': "'https://your-frontend-domain.com'", 'Access-Control-Allow-Credentials': "'true'", }, });
内容的提问来源于stack exchange,提问作者user10833069
相关产品推荐
相关产品推荐

