I'm currently facing a challenge with fetching a user's updated data from Auth0 after modifying the user_metadata:
Here is a simplified index file. In this scenario, the user chooses an object and can mark it as a favorite. When the user selects an object as a favorite, we intend to update the preference in the 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}}
})
The request is then sent to pages/api/updateMetadata, updating the user_metadata with the selected data.
// 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);
The [...auth0].tsx looks something like this.
// 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);
}
},
});
Currently, I retrieve the user_metadata each time I log in, but I need a way to refresh the user-session without logging out every time the user_metadata is updated.
If anybody has suggestions or sees any errors in my approach, please share them.
Notes:
I have attempted to use the client-side function
useUser()
, but it returns the same data as the server-side functiongetSession()
for user_data in index.tsxI've tried adding
updateSession(req, res, session)
at the end of the api/updateMetadata handlerI've included an Action in the Auth0 login flow
// 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`, );
}
};