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

Next.js+Amplify getServerSideProps调REST API报No current user

问题场景

在基于AWS Amplify + Next.js搭建的项目中,在getServerSideProps方法内发起受AWS Cognito认证保护的REST API请求时,触发No current user报错,但同一段API调用代码在客户端侧(比如useEffect钩子中)可以正常运行。

报错逻辑的实现代码如下:

export async function getServerSideProps({req}) {
  const { Auth, API } = withSSRContext({req});
 
  try {
    const apiName = "productApi-dev";
    const path = `/products`;
    products = await API.get(apiName, path); // 该调用在useEffect钩子中可正常运行
    
  } catch (e) {
    console.log(e);
  }
  return {
    props: {
      products,
    },
  };
}

在同一段getServerSideProps逻辑中加入测试代码验证用户认证状态:

const user = await Auth.currentAuthenticatedUser();
console.log(user) 

测试结果显示可以正常打印预期的用户信息,无认证相关报错。

当前项目的AWS Amplify配置如下:

Amplify.configure({
  Auth: {
    mandatorySignIn: true,
    region: "us-east-1",
    userPoolId: *****,
    userPoolWebClientId: *****,
    identityPoolId: i*****,
    signupAttributes: "EMAIL",
    secure: true,
  },

  API: {
    endpoints: [
      {
        name: "*******",
        endpoint: "https://*******.execute-api.us-east-1.amazonaws.com",
        region: "us-east-1",
        custom_header: async () => {
          return {
            Authorization: `Bearer ${(await Auth.currentSession())
              .getIdToken()
              .getJwtToken()}`,
          };
        },
      },
    ],
  },
  ssr: true,
});

根据AWS Amplify官方文档说明,withSSRContext工具可在服务端渲染路由中向GraphQL、REST后端发起认证请求,但官方示例仅给出了GraphQL请求指定authMode的用法:

movieData = await API.graphql({
    query: listMovies,
    authMode: "AMAZON_COGNITO_USER_POOLS"
  });

无REST API对应的服务端认证请求使用说明。


问题原因

报错核心原因是:全局Amplify.configure中定义的custom_header函数,内部引用的是全局导入的Auth实例,而非withSSRContext({req})生成的、绑定了当前请求上下文的服务端Auth实例。
服务端渲染时每个请求都是独立上下文,全局Auth实例没有绑定当前请求携带的Cookie认证信息,调用currentSession()时自然拿不到当前用户,才会抛出No current user错误。
在getServerSideProps里直接用withSSRContext返回的Auth调用currentAuthenticatedUser()能成功,就是因为这个返回的Auth是绑定了当前请求上下文的实例。


解决方案

不要在全局配置里写死custom_header,在服务端调用REST API时,手动从当前SSR上下文的Auth实例取Token,加到请求头里即可,有两种可落地的实现方式:

方式1:调用API时直接传入请求头(改动最小)

修改getServerSideProps中的API调用逻辑,手动生成Authorization头传入:

export async function getServerSideProps({req}) {
  const { Auth, API } = withSSRContext({req});
 
  try {
    // 从当前SSR上下文的Auth实例取会话Token
    const session = await Auth.currentSession();
    const token = session.getIdToken().getJwtToken();
    
    const apiName = "productApi-dev";
    const path = `/products`;
    // 发起请求时传入自定义头
    products = await API.get(apiName, path, {
      headers: {
        Authorization: `Bearer ${token}`
      }
    });
    
  } catch (e) {
    console.log(e);
  }
  return {
    props: {
      products,
    },
  };
}

注意:此时可以把全局配置里API端点的custom_header逻辑删掉,避免客户端侧和服务端侧逻辑冲突。

方式2:为SSR上下文单独配置API实例(适配多接口复用场景)

如果服务端有多个REST接口需要调用,不想每次重复写取Token的逻辑,可以在getServerSideProps内用当前SSR上下文单独配置一次API,把custom_header绑定到当前上下文的Auth实例:

export async function getServerSideProps({req}) {
  const { Auth, API } = withSSRContext({req});
  // 用当前SSR上下文配置API
  API.configure({
    endpoints: [
      {
        name: "productApi-dev",
        endpoint: "https://*******.execute-api.us-east-1.amazonaws.com",
        region: "us-east-1",
        // 这里的Auth是当前请求上下文的实例,能正确拿到用户会话
        custom_header: async () => {
          return {
            Authorization: `Bearer ${(await Auth.currentSession())
              .getIdToken()
              .getJwtToken()}`,
          };
        },
      },
    ]
  })
 
  try {
    const apiName = "productApi-dev";
    const path = `/products`;
    products = await API.get(apiName, path);
    
  } catch (e) {
    console.log(e);
  }
  return {
    props: {
      products,
    },
  };
}

两种方式都可以解决问题,单接口场景优先选方式1即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:15:41