NextAuth:如何在客户端获取未解码的JWT会话令牌?
如何在Next.js客户端获取NextAuth未解码的原始JWT会话令牌?
我尝试从next-auth.session-token Cookie中直接获取会话令牌,但用了多个Cookie处理库都没能拿到值。另外,我也试过在构建session对象时把token和session一起传递,但得到的是解码后的令牌,不是原始的JWT文本。
我需要这个原始JWT令牌来向Hasura(通过URQL连接)发送认证请求。目前我用了个临时方案:创建/api/me接口来返回当前用户的令牌,代码如下:
import type { NextApiRequest, NextApiResponse } from "next"; import { getToken } from "next-auth/jwt"; export default async (req: NextApiRequest, res: NextApiResponse) => { const token = await getToken({ req, raw: true }); res.status(200).json({ token }); };
然后通过这个接口的响应来实例化URQL客户端,但不想因为额外的请求浪费时间,请问有没有办法直接在客户端获取未解码的原始JWT令牌?
解决方法
方法1:通过NextAuth的回调直接返回原始令牌
在[...nextauth].ts配置文件中,修改jwt和session回调,把原始JWT令牌附加到会话对象中:
import NextAuth from "next-auth"; // 导入你的认证提供者,比如CredentialsProvider import CredentialsProvider from "next-auth/providers/credentials"; export default NextAuth({ providers: [ // 你的认证提供者配置 CredentialsProvider({ // ... 你的具体配置逻辑 }), ], // 必须启用JWT会话策略 session: { strategy: "jwt", }, callbacks: { async jwt({ token, account }) { // 登录时保存原始令牌(从account中获取) if (account?.accessToken) { token.raw = account.accessToken; } return token; }, async session({ session, token }) { // 将原始令牌附加到返回给客户端的session对象 session.rawToken = token.raw; return session; }, }, });
之后在客户端通过useSession钩子就能直接拿到原始令牌:
import { useSession } from "next-auth/react"; const { data: session } = useSession(); const rawJwtToken = session?.rawToken;
方法2:直接读取Cookie(不推荐)
如果next-auth.session-token Cookie没有设置HttpOnly属性,客户端JS可以直接读取,但强烈不建议关闭HttpOnly——这会大幅增加XSS攻击风险,导致令牌被盗。如果一定要试,可使用以下代码:
function getCookie(name: string) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop()?.split(';').shift(); } const sessionToken = getCookie('next-auth.session-token');
方法3:URQL与NextAuth集成
用URQL的authExchange插件自动处理令牌传递,无需手动获取原始JWT:
import { createClient } from 'urql'; import { authExchange } from '@urql/exchange-auth'; import { getSession } from 'next-auth/react'; const client = createClient({ url: '你的Hasura API端点', exchanges: [ authExchange({ async getAuth() { const session = await getSession(); return session?.rawToken ? `Bearer ${session.rawToken}` : null; }, addAuthToOperation(operation, authState) { if (!authState) return operation; return { ...operation, context: { ...operation.context, headers: { ...operation.context.headers, Authorization: authState, }, }, }; }, }), ], });
内容的提问来源于stack exchange,提问作者Amruth Pillai
相关产品推荐
相关产品推荐

