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

NextAuth集成Spotify API时自动刷新Access Token失败问题求助

解决NextAuth + Spotify Token自动刷新失效问题

问题根源

你的代码核心问题有两个:

  1. Session回调未同步完整Token状态:当前session回调只把access_token同步到session对象,但没有传递expires_at、refresh_token和error字段,导致页面无法感知Token是否过期或刷新失败。
  2. 页面未处理Token过期场景:第一次刷新时,JWT回调正在刷新Token,但页面拿到的还是旧的session缓存,使用过期Token请求Spotify API报错;第二次刷新时JWT已完成更新,所以恢复正常。

修复步骤

1. 完善Session回调

更新session回调,把JWT中的所有关键字段同步到session:

session({ session, token }) {
  if (session.user) {
    session.user.id = token.id as string;
    session.access_token = token.access_token as string;
    // 新增同步过期时间、刷新Token和错误状态
    session.expires_at = token.expires_at as number;
    session.refresh_token = token.refresh_token as string;
    session.error = token.error;
  }
  return session;
}

2. 页面中处理Token过期逻辑

在页面请求Spotify API前,先检查Token是否过期或刷新失败,主动触发Session刷新:

export default async function Page() {
  const session = await auth();

  if (!session?.user) return null;

  // 检查Token是否过期或刷新失败
  if (session.error === "RefreshAccessTokenError" || 
      (session.expires_at && Date.now() > session.expires_at * 1000)) {
    // 触发Session刷新,自动重新执行JWT回调获取新Token
    await signIn("spotify", { callbackUrl: "/dashboard", redirect: false });
    // 刷新页面获取最新session
    window.location.reload();
    return <div>正在刷新Token...</div>;
  }

  const accessToken = session.access_token ?? "";
  
  // 后续Spotify API请求逻辑
}

3. 优化JWT回调的时间计算(确认逻辑)

确保expires_at计算准确(Spotify返回的expires_in是秒数,转换成时间戳时要和当前时间正确相加):

expires_at: Math.floor(Date.now() / 1000) + (tokens.expires_in || 3600),

你的代码这里逻辑正确,可确认下account.expires_in是否正常获取(Spotify默认返回3600秒)。

4. API请求添加重试机制

在调用Spotify API时,捕获Token过期错误,自动重试一次:

async function fetchSpotifyData(endpoint: string, accessToken: string) {
  try {
    const res = await fetch(`https://api.spotify.com/v1/${endpoint}`, {
      headers: { Authorization: `Bearer ${accessToken}` }
    });
    
    // 捕获Token过期错误
    if (res.status === 401) {
      // 触发Session刷新
      await signIn("spotify", { callbackUrl: "/dashboard", redirect: false });
      // 获取最新session
      const newSession = await auth();
      if (!newSession?.access_token) throw new Error("Failed to refresh token");
      // 重试请求
      return fetch(`https://api.spotify.com/v1/${endpoint}`, {
        headers: { Authorization: `Bearer ${newSession.access_token}` }
      }).then(res => res.json());
    }
    
    return res.json();
  } catch (err) {
    console.error("Spotify API请求失败", err);
    throw err;
  }
}

额外注意事项

  • 确保AUTH_SPOTIFY_ID和AUTH_SPOTIFY_SECRET环境变量配置正确,无拼写错误。
  • 检查Spotify开发者后台的重定向URI是否和NextAuth配置一致。
  • 若使用Next.js App Router,确保auth()调用在Server Component中(你的代码逻辑符合要求)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:35:20