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

Next.js-Auth0:更新user_metadata后无需登出刷新用户会话

问题

在Next.js集成Auth0时,更新user_metadata后无法实时获取用户最新数据,必须登出再登录才能看到变化。相关代码如下:

前端页面(index.tsx)

// index.tsx

export default function home({user_data, some_data}) {

   const [selected, setSelect] = useState(null)
   
   async function handleAddToFavourite() {
      if (selected) {
         const data = await axios.patch("api/updateMetadata", {some_favorite: selected.id})
         // Errorhandling ...
      }
   }

   return (
      <div>
         <SearchData setData={setSelect} data={some_data}/>
         <Button onClick={handleAddToFavorite}>Add to Favorite</Button>
         <div>Selected: {selected.id}</div>
         <div>My Favorite: {user_data.user_metadata.some_favorite}</div>
      </div>
  )
}

export const getServerSideProps = withPageAuthRequired({
   returnTo: "/foo",
   async getServerSideProps(ctx) {
     const session = await getSession(ctx.req, ctx.res)
     const {data} = await axios.get("https://somedata.com/api")

   return {props: {some_data: data, user_data: session.user}}
})

后端接口(api/updateMetadata.ts)

// api/updateMetadata.ts
async function handler(req: NextApiRequest, res: NextApiResponse) {

  const session = await getSession(req, res);

  if (!session || session === undefined || session === null) {
    return res.status(401).end();
  }

  const id = session?.user?.sub;
  const { accessToken } = session;

  const currentUserManagementClient = new ManagementClient({
    token: accessToken,
    domain: auth0_domain.replace('https://', ''),
    scope: process.env.AUTH0_SCOPE,
  });

  const user = await currentUserManagementClient.updateUserMetadata({ id }, req.body);

  return res.status(200).json(user);
}

export default withApiAuthRequired(handler);

Auth0配置(pages/api/auth/[...auth0].tsx)

// pages/api/auth/[...auth0].tsx
export default handleAuth({
  async profile(req, res) {
    try {
      await handleProfile(req, res, {
        refetch: true,
      });
    } catch (error: any) {
      res.status(error.status || 500).end(error.message);
    }
  },
  async login(req, res) {
    try {
      await handleLogin(req, res, {
        authorizationParams: {
          audience: `${process.env.AUTH0_ISSUER_BASE_URL}/api/v2/`,
          scope: process.env.AUTH0_SCOPE,
        },
      });
    } catch (error: any) {
      res.status(error.status || 400).end(error.message);
    }
  },
});

已尝试的无效方案

  • 使用客户端函数useUser(),返回数据与服务端getSession()一致,无更新
  • 在updateMetadata接口末尾添加updateSession(req, res, session)
  • 在Auth0登录流中添加PostLogin Action(存在语法错误):
// Auth0 action flow - login
exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'https://example.com';
  const { some_favorite } = event.user.user_metadata;

  if (event.authorization) {
    // Set claims 
    api.idToken.setCustomClaim(`${namespace}/some_favorite`, );
  }
};

可行解决方案及错误分析

1. 修复PostLogin Action的语法与逻辑错误

原Action缺少赋值变量,且未同步更新Access Token,修改后:

exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'https://example.com';
  const { some_favorite } = event.user.user_metadata;

  if (event.authorization && some_favorite) {
    // 同时更新ID Token和Access Token,确保前后端都能获取最新值
    api.idToken.setCustomClaim(`${namespace}/some_favorite`, some_favorite);
    api.accessToken.setCustomClaim(`${namespace}/some_favorite`, some_favorite);
  }
};

2. 更新后端接口,同步会话数据

更新user_metadata后,需重新从Auth0拉取最新用户信息并更新会话,不能直接使用旧的session对象:

// api/updateMetadata.ts
async function handler(req: NextApiRequest, res: NextApiResponse) {
  const session = await getSession(req, res);

  if (!session) {
    return res.status(401).end();
  }

  const id = session?.user?.sub;
  const { accessToken } = session;

  const currentUserManagementClient = new ManagementClient({
    token: accessToken,
    domain: auth0_domain.replace('https://', ''),
    scope: process.env.AUTH0_SCOPE,
  });

  // 更新用户元数据
  const updatedUser = await currentUserManagementClient.updateUserMetadata({ id }, req.body);
  
  // 重新获取完整的最新用户信息
  const freshUser = await currentUserManagementClient.getUser({ id });
  
  // 更新会话中的用户数据
  session.user = { ...session.user, ...freshUser };
  await updateSession(req, res, session);

  return res.status(200).json(updatedUser);
}

export default withApiAuthRequired(handler);

3. 前端主动刷新状态或用户数据

调用更新接口成功后,通过两种方式同步前端显示:

  • 方式一:用接口返回的更新数据直接修改本地状态
export default function home({user_data, some_data}) {
   const [selected, setSelect] = useState(null)
   const [favorite, setFavorite] = useState(user_data.user_metadata.some_favorite)
   
   async function handleAddToFavourite() {
      if (selected) {
         const { data: updatedUser } = await axios.patch("api/updateMetadata", {some_favorite: selected.id})
         // 直接更新本地状态
         setFavorite(updatedUser.user_metadata.some_favorite)
      }
   }

   return (
      <div>
         <SearchData setData={setSelect} data={some_data}/>
         <Button onClick={handleAddToFavorite}>Add to Favorite</Button>
         <div>Selected: {selected?.id}</div>
         <div>My Favorite: {favorite}</div>
      </div>
  )
}
  • 方式二:调用Auth0的refresh方法刷新用户会话
import { useUser } from '@auth0/nextjs-auth0';

export default function home({user_data, some_data}) {
   const { user, refresh } = useUser();
   const [selected, setSelect] = useState(null)
   const [favorite, setFavorite] = useState(user?.user_metadata?.some_favorite)
   
   async function handleAddToFavourite() {
      if (selected) {
         await axios.patch("api/updateMetadata", {some_favorite: selected.id})
         // 刷新用户会话,拉取最新数据
         await refresh();
         // 更新本地状态
         setFavorite(user.user_metadata.some_favorite)
      }
   }

   return (
      <div>
         <SearchData setData={setSelect} data={some_data}/>
         <Button onClick={handleAddToFavorite}>Add to Favorite</Button>
         <div>Selected: {selected?.id}</div>
         <div>My Favorite: {favorite}</div>
      </div>
  )
}

4. 确认handleProfile配置有效性

你当前在[...auth0].tsx中设置的refetch: true是正确的,确保调用/api/auth/me时会从Auth0重新拉取最新用户数据,无需修改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:10:13