Next-auth - 如何更新会话客户端?

Yoa*_*net 17 javascript next-auth

我设法使用新的用户数据更新我的会话服务器端,但是在将其分配给 [...nextauth.js] 中的会话对象后,我的会话客户端仍然是旧的。如果我使用它,它不会刷新getSession()

此代码适用于后端:

callbacks.session = async function session({ session, token }) {
  // we can fetch info from back end here to add it to the session   
  session.user = token.user;
  session.jti = token.jti;

  // If user is logged, we refresh his session
  if (token?.user?.id) {
    const url = routes.api.entities.shop.get.byId.build(token?.user?.id);
    let apiResp = await axios.get(url, {});
    session.user = { ...apiResp.data };
    token.user = { ...apiResp.data };
  }

  return session;
};
Run Code Online (Sandbox Code Playgroud)

如何刷新前端的会话?

Yoa*_*net 38

2023 年更新: 从 v4.22.1 开始,现在有一种官方方法可以做到这一点。请参阅此处和更新的文档

你现在得到一个像这样的更新函数:

  const { update } = useSession();
Run Code Online (Sandbox Code Playgroud)

注意: update fn不会同步 tabs 之间的会话对象,因此如果您打开了多个选项卡,则每个选项卡需要单独执行reloadSession()

以前的答案:

没有简单的官方方法可以做到这一点,贡献者仍在讨论中。

也就是说,有一个办法。如果您单击另一个选项卡,然后单击您的应用程序的选项卡,Next-auth 会刷新会话。它发生了,这是一个我们可以重现的 javascript 事件。

所以只需定义一个方法来做到这一点:

const reloadSession = () => {
  const event = new Event("visibilitychange");
  document.dispatchEvent(event);
};
Run Code Online (Sandbox Code Playgroud)

调用它,然后..你就完成了。会话确实刷新了。

reloadSession();
Run Code Online (Sandbox Code Playgroud)

有关更多信息,此行为来自这部分代码

  • 这不适用于 V4 (4认同)
  • 这适用于我的下一个身份验证版本 4.10.3 (3认同)
  • 作为参考,[this](https://github.com/nextauthjs/next-auth/issues/596#issuecomment-943453568) 是 GitHub 上推荐此黑客的地方 (2认同)

Bal*_*áni 6

使用模拟选项卡开关的技巧在 v4 中不再起作用。

您可以做的是将回调更新为session?update.

const createOptions = (req) => ({
  // ...
  callbacks: {
    async jwt({ token, ...params }) {
      if (req.url === "/api/auth/session?update") {
          const response = await fetch(`${process.env.NEXT_PUBLIC_URL}/api/users/get/${token.email}`);
          const newUser = await response.json();
          token.hasAcceptedTerms = newUser.hasAcceptedTerms;
      }
      return token;
    },
    async session({ session, token }) {
        if (session.user != null && token.hasAcceptedTerms != null) {
            session.user.hasAcceptedTerms = token?.hasAcceptedTerms;
        }

        return Promise.resolve(session);
     },
  },
});

export default async (req, res) => {
  return NextAuth(req, res, createOptions(req));
};
Run Code Online (Sandbox Code Playgroud)

然后在您的客户端中您可以拨打电话

  await axios.get('/api/auth/session?update');
Run Code Online (Sandbox Code Playgroud)

向 github 上的这个答案致敬。