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

AWS Cognito与Amplify跨应用会话获取:配置Amplify通过next-auth.session-token Cookie调用Auth.currentSession()

解决Amplify Auth无法读取NextAuth生成的Cognito会话问题

核心问题很明确:Amplify Auth默认只会识别自己创建的Cognito会话Cookie,而你的认证流程是通过NextAuth完成的,生成的Cookie是next-auth.session-token,Amplify并不知道如何从这个Cookie里提取有效会话信息。下面是一步步的解决思路和代码实现:

1. 先确保NextAuth的Cookie支持跨端口访问

首先得让4200端口的应用能读取到3000端口生成的next-auth.session-token,需要调整NextJS应用里的NextAuth配置:

// NextJS应用中的[...nextauth].js文件
export default NextAuth({
  providers: [
    // 这里保留你已有的Cognito配置
  ],
  session: {
    strategy: "jwt",
  },
  cookies: {
    sessionToken: {
      name: 'next-auth.session-token',
      domain: 'localhost', // 允许所有localhost下的端口共享这个Cookie
      path: '/',
      sameSite: 'lax',
      secure: false, // 本地http环境设为false,生产环境记得改成true
      httpOnly: true,
    },
  },
  // 其他原有配置...
});

2. 自定义Amplify的存储适配器

Amplify允许我们替换默认的存储逻辑,这样就能让Auth模块从next-auth.session-token里解析出Cognito的会话数据。

步骤2.1 解析NextAuth的Session Token

NextAuth的next-auth.session-token是一个JWT,里面包含了Cognito的idToken、accessToken等核心信息,先写工具函数获取并解析它:

// 获取指定名称的Cookie
const getCookie = (name) => {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
};

// 解析NextAuth的JWT,提取Cognito令牌信息
const parseNextAuthSession = () => {
  const sessionToken = getCookie('next-auth.session-token');
  if (!sessionToken) return null;
  
  // JWT分为三段,中间的是payload,base64解码
  const payload = sessionToken.split('.')[1];
  // 处理base64可能的填充问题
  const decodedPayload = JSON.parse(atob(payload.padEnd(payload.length + (4 - payload.length % 4) % 4, '=')));
  
  return {
    idToken: decodedPayload.idToken,
    accessToken: decodedPayload.accessToken,
    refreshToken: decodedPayload.refreshToken,
    expiresIn: decodedPayload.expiresAt - Date.now() / 1000, // 转成秒数
    tokenType: 'Bearer'
  };
};

步骤2.2 实现Amplify兼容的自定义存储类

Amplify Auth会查找特定格式的存储key,我们需要实现一个存储类,把解析后的NextAuth会话数据映射成Amplify需要的格式:

class CustomAuthStorage {
  async getItem(key) {
    const sessionData = parseNextAuthSession();
    if (!sessionData) return null;
    
    // 替换成你的Cognito Web客户端ID
    const clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXX";
    // 从idToken里提取用户名
    const idTokenPayload = JSON.parse(atob(sessionData.idToken.split('.')[1]));
    const username = idTokenPayload.username;

    // 根据Amplify需要的key返回对应数据
    switch(key) {
      case `CognitoIdentityServiceProvider.${clientId}.LastAuthUser`:
        return username;
      case `CognitoIdentityServiceProvider.${clientId}.${username}.idToken`:
        return sessionData.idToken;
      case `CognitoIdentityServiceProvider.${clientId}.${username}.accessToken`:
        return sessionData.accessToken;
      case `CognitoIdentityServiceProvider.${clientId}.${username}.refreshToken`:
        return sessionData.refreshToken;
      case `CognitoIdentityServiceProvider.${clientId}.${username}.tokenScopesString`:
        return 'email profile openid'; // 对应你的OAuth scope
      case `CognitoIdentityServiceProvider.${clientId}.${username}.expiresIn`:
        return sessionData.expiresIn.toString();
      default:
        return null;
    }
  }

  // 因为我们不需要修改会话,以下方法可以空实现
  async setItem(key, value) {}
  async removeItem(key) {}
  async clear() {}
}

步骤2.3 把自定义存储配置到Amplify

修改你的Amplify配置,用自定义存储替换默认的cookieStorage:

Amplify.configure({ 
  region: "eu-west-1", 
  userPoolId: "eu-west-1_XXXXXXXXX", 
  userPoolWebClientId: "XXXXXXXXXXXXXXXXXXXXXXXXXX", 
  // OAuth配置可以保留,但核心认证逻辑已经通过NextAuth完成
  oauth: { 
    domain: "XXXXXXXXXXX.auth.eu-west-1.amazoncognito.com", 
    scope: ['email', 'profile', 'openid'], 
    redirectSignIn: "http://localhost:4200/", 
    redirectSignOut: "http://localhost:3000/", 
    responseType: 'token', 
  }, 
  // 指定自定义存储
  storage: new CustomAuthStorage()
}); 

// 现在再调用Auth.currentSession()应该就能拿到会话了
Auth.currentSession() 
  .then((response) => { 
    console.log('response=', response); 
  }) 
  .catch((error) => { 
    console.error('error=', error); 
  });

3. 关键注意事项

  • 跨域Cookie验证:确保NextAuth的Cookie设置了domain: 'localhost',否则不同端口的应用无法共享Cookie。
  • JWT解码兼容:如果遇到base64解码错误,记得处理填充问题(代码里已经加了padEnd处理)。
  • 存储key匹配:Amplify的存储key格式是固定的,一定要替换成你自己的Cognito客户端ID,否则会匹配失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 21:28:10