Nextjs-auth0: обновить сеанс пользователя (без выхода/входа) после обновления user_metadata

В настоящее время я пытаюсь восстановить данные пользователя из Auth0 после обновления user_metadata:

Ниже упрощенный индексный файл. пользователь выбирает какой-либо объект, и ему будет предложено добавить этот объект (или идентификатор объекта) в избранное. Если пользователь хочет выбрать этот объект в качестве избранного, мы хотим обновить предпочтение в 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 каждый раз, когда я вхожу в систему, однако мне нужно выйти из системы и снова войти в систему, чтобы увидеть, как изменения вступили в силу. Мне нужно как-то обновить сеанс пользователя без выхода из системы каждый раз, когда обновляются метаданные пользователя.

Кто-нибудь знает обходные пути для достижения того, что я пытаюсь сделать, и, возможно, видит какие-либо ошибки?

Заранее спасибо!

Примечания:

  • Я попытался использовать клиентскую функцию useUser(), но это дает те же данные, что и серверная функция getSession() для user_data в index.tsx.

  • Я попытался добавить updateSession(req, res, session) в конце обработчика api/updateMetadata.

  • Я добавил действие в поток входа 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`, );
  }
};


Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
122
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я понял это, я опубликую свое решение на случай, если кто-то еще застрянет с той же проблемой :)

В 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) // ...

Затем я использовал checkSession() из useUser в клиентском коде сразу после получения данных.

// 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 для входа в систему также является правильным.

Надеюсь, это поможет кому-то :)

Другие вопросы по теме