簡體   English   中英

nextjs-auth0:更新用戶元數據后更新用戶 session(無需注銷/登錄)

[英]nextjs-auth0: update user session (without logging out/in) after updating user_metadata

更新 user_metadata 后,我目前正在努力從 Auth0 重新獲取用戶數據:

下面是一個簡化的索引文件 用戶選擇一些 object,然后將被要求將此 object(或對象 ID)添加為收藏夾。 如果用戶想要將 select 這個 object 作為收藏,我們要更新 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 時,我都需要以某種方式刷新用戶會話而不注銷。

有沒有人知道實現我正在嘗試做的事情的任何解決方法,並且可能會看到任何錯誤?

提前致謝!

筆記:

  • 我嘗試使用客戶端 function useUser(),但這會產生與服務器端 function getSession() 相同的數據,用於 index.tsx 中的 user_data

  • 我嘗試在 api/updateMetadata 處理程序的末尾添加 updateSession(req, res, session)

  • 我在 Auth0 登錄流程中添加了一個操作

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


我想通了,我會發布我的解決方案,以防其他人遇到同樣的問題:)

在 api/updateMetadata.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 操作流程也是正確的。

希望這對某人有幫助:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM