next.js 下一个js-auth 0:更新user_metadata后更新用户会话(不注销/登录)

whhtz7ly  于 2022-12-29  发布在  其他
关注(0)|答案(1)|浏览(95)

更新user_metadata后,我目前正努力从Auth 0重新获取用户数据:
下面是一个简化的索引文件。用户选择某个对象,系统会要求将该对象(或对象id)添加为收藏夹。如果用户希望将该对象选择为收藏夹,我们希望更新user_metadata中的首选项。

// 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}}
})

然后将请求发送到 pages/API/updateMetadata,并使用所选数据更新user_metadata。

// 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].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);
    }
  },
});

现在,我每次登录时都会获得user_metadata,但是,我需要注销并再次登录才能看到更改生效。每次更新user_metadata时,我需要在不注销的情况下以某种方式刷新user-session。

有没有人知道实现我正在尝试做的事情的任何变通方法,或者看到任何错误?

提前感谢

  • 备注:*
  • 我尝试过使用客户端函数useUser(),但是对于index.tsx中的user_data,这会产生与服务器端函数getSession()相同的数据
  • 我尝试过在API/updateMetadata处理程序的末尾添加updateSession(req,res,session)
  • 我已将Action添加到Auth 0登录流
// 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`, );
  }
};
uinbv5nw

uinbv5nw1#

我想出来了,我会张贴我的解决方案,以防其他人陷入同样的问题:)
在api/更新元数据. ts中:

// api/updateMetadata.ts

import { updateSession , ...  } from '@auth0/nextjs-auth0';
// ...
// ...
const user = await currentUserManagementClient.updateUserMetadata({ id }, req.body);

await updateSession(req, res, { ...session, user }); // Add this to update the session

return res.status(200) // ...

然后,在获取数据之后,我立即在客户端代码中的useUser中使用checkSession()。

// index.tsx

import { useUser } from '@auth0/nextjs-auth0/client'

//...

   async function handleAddToFavourite() {
      if (selected) {
         const data = await axios.patch("api/updateMetadata", {some_favorite: selected.id})
         // Update the user session for the client side
         checkSession()
         // Errorhandling ...
      }
   }

//...

现在,这是什么使它工作,修改profileHandler:

// pages/api/auth/[...auth0].tsx

// Updating with the new session from the server
const afterRefetch = (req, res, session) => {
     const newSession = getSession(req, res)
     if (newSession) {
          return newSession as Promise<Session>
     }
     return session
}

export default handleAuth({
  async profile(req, res) {
    try {
      await handleProfile(req, res, {
        refetch: true,
        afterRefetch // added afterRefetch Function
      });
    } catch (error: any) {
      res.status(error.status || 500).end(error.message);
    }
  },

  // ...

});

此外,值得注意的是,登录的Auth0操作流也是正确的。
希望这对某人有帮助:)

相关问题