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

如何在Lambda函数中以owner权限调用AWS Amplify GraphQL API?

问题描述

Schema定义

type Notification
  @auth(rules: [{ allow: owner, operations: [create, read, update] }])
  @model {
  content: String!
  id: ID!
}

Lambda相关代码

const createNotificationRequest = new Request(
  process.env.API_PROJECT_GRAPHQLAPIENDPOINTOUTPUT,
  {
    body: JSON.stringify({
      query: /* GraphQL */ `
                mutation CreateNotification(
                  $input: CreateNotificationInput!
                  $condition: ModelNotificationConditionInput
                ) {
                  createNotification(input: $input, condition: $condition) {
                    content
                    id
                    createdAt
                    updatedAt
                    owner
                  }
                }
              `,
      variables: {
        input: {
          content: "yo",
          owner: `${sub}::${username}`,
        },
      },
    }),
    headers: {
      // Authorization: somethingGoesHere,
      "Content-Type": "application/json",
    },
    method: "POST",
  }
);
const createNotificationRequestResult = await fetch(
  createNotificationRequest
);
console.log(createNotificationRequestResult);

请求返回结果

Response {
  size: 0,
  timeout: 0,
  [Symbol(Body internals)]: {
    body: PassThrough {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 2,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: null
    },
    disturbed: false,
    error: null
  },
  [Symbol(Response internals)]: {
    url: 'https://abcdefg.appsync-api.us-east-1.amazonaws.com/graphql',
    status: 401,
    statusText: 'Unauthorized',
    headers: Headers { [Symbol(map)]: [Object: null prototype] },
    counter: 0
  }
}

Lambda函数无法以owner权限创建Notification对象(已获取该owner的sub和username),尝试给Lambda添加IAM权限但未生效,询问能否实现该需求。


解决方案

方式一:IAM授权+AppSync规则修正

这是最适配现有架构的方案,需要两步配置:

  1. 给Lambda附加AppSync权限
    给Lambda的IAM角色添加如下策略,限定只允许调用目标Mutation:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": "appsync:GraphQL",
          "Resource": "arn:aws:appsync:us-east-1:YOUR_ACCOUNT_ID:apis/YOUR_API_ID/types/Mutation/fields/createNotification"
        }
      ]
    }
    

    替换其中的YOUR_ACCOUNT_ID和YOUR_API_ID为实际值。

  2. 修改Schema的认证规则
    新增一条IAM授权规则,允许Lambda在指定条件下创建数据(确保传入的owner和身份匹配):

    type Notification
      @auth(rules: [
        { allow: owner, operations: [create, read, update] },
        { 
          allow: iam, 
          operations: [create],
          condition: { eq: ["${ctx.args.input.owner}", "${ctx.identity.username}"] }
        }
      ])
      @model {
      content: String!
      id: ID!
    }
    
  3. Lambda请求添加IAM签名
    使用AWS SDK的签名工具给请求添加授权头,示例代码:

    import { SignatureV4 } from "@aws-sdk/signature-v4";
    import { Sha256 } from "@aws-crypto/sha256-js";
    import { defaultProvider } from "@aws-sdk/credential-provider-node";
    
    const signer = new SignatureV4({
      credentials: defaultProvider(),
      region: process.env.AWS_REGION,
      service: "appsync",
      sha256: Sha256,
    });
    
    const request = new Request(
      process.env.API_PROJECT_GRAPHQLAPIENDPOINTOUTPUT,
      {
        body: JSON.stringify({
          query: /* GraphQL */ `
            mutation CreateNotification($input: CreateNotificationInput!) {
              createNotification(input: $input) {
                content
                id
                owner
              }
            }
          `,
          variables: { input: { content: "yo", owner: `${sub}::${username}` } },
        }),
        headers: {
          "Content-Type": "application/json",
          host: new URL(process.env.API_PROJECT_GRAPHQLAPIENDPOINTOUTPUT).hostname,
        },
        method: "POST",
      }
    );
    
    const signedRequest = await signer.sign(request);
    const response = await fetch(signedRequest);
    const data = await response.json();
    

方式二:模拟用户JWT(Cognito场景)

如果系统用Cognito用户池做认证,可以直接获取目标用户的ID Token,放在请求头中:

headers: {
  "Authorization": "USER_ID_TOKEN_HERE",
  "Content-Type": "application/json",
},

AppSync会解析令牌中的sub和username,自动匹配owner规则。需要确保Lambda有获取用户令牌的权限(比如调用Cognito的adminInitiateAuth接口)。

方式三:直接操作DynamoDB(更高效)

跳过AppSync的HTTP调用,让Lambda直接操作@model生成的DynamoDB表:

  1. 给Lambda添加DynamoDB的PutItem权限
  2. 使用AWS SDK直接写入数据:
    import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";
    import { marshall } from "@aws-sdk/util-dynamodb";
    
    const client = new DynamoDBClient({ region: process.env.AWS_REGION });
    const command = new PutItemCommand({
      TableName: "Notification",
      Item: marshall({
        id: "UUID_GENERATED",
        content: "yo",
        owner: `${sub}::${username}`,
        createdAt: new Date().toISOString(),
        updatedAt: new Date().toISOString()
      })
    });
    await client.send(command);
    
    这种方式不需要处理AppSync的认证逻辑,性能更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:54:59