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

NextJs 14 App Router SSR路由中Amplify GraphQL无凭证问题求助

你遇到的核心问题是:Stripe 发起的 Webhook 请求是从 Stripe 服务器直接发送到你的 Next.js Route Handler,完全不包含用户浏览器的认证 Cookie。不管你怎么配置 Amplify 的 SSR 模式,这里都拿不到用户的凭证——因为这个请求和用户的前端会话没有关联。

之前尝试的 Amplify SSR 配置(比如ssr: true)只适用于用户发起的前端请求(比如页面渲染、客户端 API 调用),但 Webhook 属于服务端到服务端的请求,不会携带用户的 Cookie,所以必然会出现"No Credentials"错误。


解决方案:使用服务端级别的授权调用 AppSync

针对 Webhook 场景,你需要绕过用户级别的认证,用服务端凭证直接调用 AppSync。推荐两种可行方案:

方案一:使用 IAM 角色授权(生产环境推荐)

步骤1:配置 Amplify 服务端客户端(基于 IAM)

修改你的amplifyServerUtils.ts,创建一个用 IAM 初始化的客户端,不需要依赖用户 Cookie:

// amplifyServerUtils.ts
import { Amplify } from 'aws-amplify';
import { generateClient } from 'aws-amplify/api';
import amplifyConfig from '../amplifyconfiguration.json';
import { defaultProvider } from '@aws-sdk/credential-provider-node';

// 初始化 Amplify 服务端配置
Amplify.configure({
  ...amplifyConfig,
  Auth: {
    credentialsProvider: defaultProvider() // 使用 Node.js 默认凭证链(本地用~/.aws/credentials,生产用ECS/EKS角色)
  }
}, { ssr: true });

// 创建服务端专用的 GraphQL 客户端
export const serverIAMClient = generateClient();

步骤2:更新 AppSync API 权限

在 AppSync 控制台中,修改createTransaction mutation 的权限规则,允许你的 IAM 角色执行该操作:

  • 打开 AppSync 控制台 → 你的 API → 架构 → 找到createTransaction
  • 添加如下权限规则(替换为你的 IAM 角色 ARN):
type Transaction @model @auth(rules: [
  { allow: private, provider: iam }, // 允许IAM角色调用
  { allow: owner, ownerField: "userId" } // 保留用户级别的所有者权限
]) {
  // 你的 Transaction 字段...
}

步骤3:在 Route Handler 中使用服务端客户端

修改route.ts中的 GraphQL 请求部分:

// 在 payment_intent.succeeded 分支中替换原请求代码
try {
  const result = await serverIAMClient.graphql({
    query: createTransaction,
    variables: {
      transaction: transactionInput
    },
  });
  console.log("createTransaction result transactionId = ", result.data.createTransaction?.transactionId);
} catch (error) {
  console.log("createTransaction failed with error: ", error);
}

方案二:使用 API Key 授权(测试/快速验证用)

如果只是快速验证功能,可以用 AppSync 的 API Key 直接调用,不需要 IAM 配置:

步骤1:修改服务端客户端配置

// amplifyServerUtils.ts
import { Amplify } from 'aws-amplify';
import { generateClient } from 'aws-amplify/api';
import amplifyConfig from '../amplifyconfiguration.json';

Amplify.configure({
  ...amplifyConfig,
  API: {
    GraphQL: {
      apiKey: process.env.APPSYNC_API_KEY // 从环境变量获取API Key
    }
  }
}, { ssr: true });

export const serverAPIKeyClient = generateClient();

步骤2:更新 AppSync 权限

确保createTransaction允许 API Key 访问:

type Transaction @model @auth(rules: [
  { allow: apiKey }, // 允许API Key调用
  { allow: owner, ownerField: "userId" }
]) {
  // 字段...
}

步骤3:在 Route Handler 中使用该客户端

和方案一类似,替换为serverAPIKeyClient即可。


额外注意点:获取真实的 userId

你当前代码中userId: '1234'是硬编码的,正确的做法是:

  1. 在前端创建 Payment Intent时,把当前用户的 ID 存入 Payment Intent 的metadata中:
// 前端代码(比如 checkout 页面)
const { data } = await stripe.createPaymentIntent({
  amount: 1000,
  currency: 'usd',
  metadata: {
    userId: user.id // 从 Amplify Auth 获取当前用户ID
  }
});
  1. 在 Webhook 中从 Payment Intent 取出metadata.userId:
// route.ts 中 payment_intent.succeeded 分支
const userId = paymentIntentSucceeded.metadata.userId;
const transactionInput: TransactionInput = {
  userId: userId,
  // 其他字段...
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 20:53:19