如何将会话中的access token插入Next-Auth对接Spotify的API请求头
问题根因
getInitialProps是独立于组件的运行逻辑,作用域内无法读取组件内通过useSession获取的session变量,你直接调用session.user.accessToken会触发未定义报错- 你当前的session回调没有把JWT中存储的
accessToken暴露到会话对象中,即便正确拿到session也无法读取token值 - JWT回调的参数顺序有误,无法正确在首次授权时捕获Spotify返回的accessToken
修正步骤
1. 调整[...nextauth].js配置
import NextAuth from "next-auth" import Spotify from "../../../providers/spotify" import Twitch from "../../../providers/twitch" export default (req, res) => NextAuth(req, res, { providers: [ Spotify({ clientId: process.env.SPOTIFY_CLIENT_ID, clientSecret: process.env.SPOTIFY_CLIENT_SECRET, }), Twitch({ clientId: process.env.TWITCH_CLIENT_ID, clientSecret: process.env.TWITCH_CLIENT_SECRET, }) ], callbacks: { // 修正参数顺序,首次授权时从account中取token async jwt(token, user, account) { // 首次登录时把Spotify返回的token存入JWT if (account?.accessToken) { token.accessToken = account.accessToken // 可选:存储refresh token和过期时间,用于后续token刷新 token.refreshToken = account.refreshToken token.expiresAt = account.expires_at * 1000 } return token }, async session(session, token) { // 把JWT中的token暴露给session对象 session.accessToken = token.accessToken session.user = token.user || token return session } }, })
2. 调整页面请求逻辑
在getInitialProps中使用getSession方法从请求上下文获取会话,再把token带入请求头:
import axios from "axios"; import { VStack, Heading, Text } from "@chakra-ui/layout"; import { getSession, useSession } from 'next-auth/client' const Spotify = ({ Spotify, error }) => { const [ session, loading ] = useSession(); if (loading) return <div>登录校验中...</div> if (!session) return <div>请先登录Spotify账号</div> if (error) return <div>获取播放列表失败:{error.message}</div> if(!Spotify) return <div>加载中...</div> return ( <VStack> {Spotify.map((Spoty) => ( <div key={Spoty.id}> <Heading>{Spoty.name}</Heading> <Text>链接: {Spoty.href}</Text> <Text>创建者: {Spoty.owner.display_name}</Text> </div> ))} </VStack> ); }; Spotify.getInitialProps = async (ctx) => { // 从请求上下文获取session const session = await getSession(ctx) if (!session) return { Spotify: null, error: new Error('未登录') } try { const res = await axios.get("https://api.spotify.com/v1/me/playlists", { headers: { Authorization: `Bearer ${session.accessToken}` } }); return { Spotify: res.data.items, error: null }; } catch (error) { return { Spotify: null, error }; } }; export default Spotify;
补充说明
如果需要处理Spotify accessToken过期的问题,可以在JWT回调中增加逻辑,当token快过期时用refreshToken换取新的有效token,避免接口请求鉴权失败。
内容的提问来源于stack exchange,提问作者MatDoak
相关产品推荐
相关产品推荐

