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

AWS Lambda Authorizer返回BadRequestException问题排查求助

排查AWS Lambda自定义授权返回BadRequestException问题

你遇到的BadRequestException: Unknown error at buildRestApiServiceError通常是Lambda授权器返回了不符合AppSync要求的响应,或者代码内部抛出未处理的错误导致的。以下是具体排查点和修正方案:

一、Lambda代码中的明显错误

1. 未定义变量导致运行时错误

代码中直接使用了purchasedPhones和userId两个未声明的变量,会触发ReferenceError,导致Lambda返回异常响应:

// 错误:purchasedPhones未定义
for (let index = 0; index < purchasedPhones.length; index++) {
  // ...
}

// 错误:userId未定义
return {
  isAuthorized: isPurchased,
  resolverContext: {
    userid: userId,
    // ...
  },
  // ...
};

修正方案:

  • 从DynamoDB返回结果中提取已购手机列表(假设RecordTable的Item包含purchasedPhones字段):
    // 假设字段为字符串集合类型(SS)
    const purchasedPhones = response.Item?.purchasedPhones?.SS || [];
    // 如果是列表类型(L),则用:
    // const purchasedPhones = response.Item?.purchasedPhones?.L?.map(item => item.S) || [];
    
  • 从Cognito用户信息中获取userId(推荐用用户sub而非username):
    const userId = user.UserAttributes.find(attr => attr.Name === 'sub').Value;
    

2. DynamoDB查询结果未做空值判断

如果用户在RecordTable中无记录,response.Item会是undefined,直接访问字段会报错,需先判断:

let purchasedPhones = [];
if (response.Item) {
  purchasedPhones = response.Item.purchasedPhones.SS || [];
}

3. 错误获取GraphQL查询参数

AppSync传递给Lambda的event中不存在requestContext.queryString,GraphQL变量在event.arguments里,目标手机ID应从这里获取:

// 错误写法
const { requestContext: { queryString } } = event;
// 正确写法
const targetPhoneId = event.arguments.id;

同时修改授权判断逻辑:

const isPurchased = purchasedPhones.includes(targetPhoneId);

4. Catch块直接返回Error对象

Lambda自定义授权器必须返回符合AppSync要求的JSON结构,直接返回Error对象会导致解析失败,修改catch块:

catch (error) {
  console.error('Authorization error:', error);
  return {
    isAuthorized: false,
    ttlOverride: 300
  };
}

5. Cognito客户端未指定区域

若Lambda与Cognito用户池区域不同,未指定区域会导致请求失败,需显式配置:

const cognitoClient = new CognitoIdentityProviderClient({ 
  region: process.env.REGION 
});
const dynamoClient = new DynamoDBClient({ 
  region: process.env.REGION 
});

二、其他排查点

1. 确认授权令牌类型

GetUserCommand要求传入Cognito AccessToken,如果前端传递的是IdToken,会触发Cognito错误。若使用IdToken,可直接解析JWT获取sub:

const jwt = require('jsonwebtoken');
const decoded = jwt.decode(authorizationToken);
const userId = decoded.sub;

2. 检查AppSync自定义授权器配置

  • 确保在AppSync控制台将该Lambda配置为自定义授权器,并关联到read操作。
  • 验证令牌来源是否设置为Authorization头。

3. 查看Lambda CloudWatch日志

AppSync返回的错误只是表层信息,真正原因在Lambda执行日志中。去CloudWatch控制台找到对应日志组,查看具体错误(如变量未定义、Cognito调用失败等),这是最关键的排查步骤。

修正后的Lambda代码示例

exports.handler = async (event) => {
  console.log(`EVENT: ${JSON.stringify(event)}`);
  const { authorizationToken, arguments: { id: targetPhoneId } } = event;

  try {
    // 初始化客户端并指定区域
    const cognitoClient = new CognitoIdentityProviderClient({ region: process.env.REGION });
    const cognitoInput = { AccessToken: authorizationToken };
    const cognitoCommand = new GetUserCommand(cognitoInput);
    const user = await cognitoClient.send(cognitoCommand);
    
    // 获取用户sub作为userId
    const userId = user.UserAttributes.find(attr => attr.Name === 'sub').Value;

    // 查询RecordTable(注意主键用sub而非username,需与表结构匹配)
    const dynamoClient = new DynamoDBClient({ region: process.env.REGION });
    const dynamoInput = {
      Key: { id: { S: userId } },
      TableName: "RecordTable",
    };
    const dynamoCommand = new GetItemCommand(dynamoInput);
    const response = await dynamoClient.send(dynamoCommand);

    // 提取已购手机列表
    let purchasedPhones = [];
    if (response.Item?.purchasedPhones) {
      purchasedPhones = response.Item.purchasedPhones.SS || [];
    }

    // 判断是否购买过目标手机
    const isPurchased = purchasedPhones.includes(targetPhoneId);

    return {
      isAuthorized: isPurchased,
      resolverContext: {
        userid: userId,
        info: user,
        more_info: response,
      },
      ttlOverride: 300,
    };
  } catch (error) {
    console.error('Authorization failed:', error);
    return {
      isAuthorized: false,
      ttlOverride: 300
    };
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:14:57