Metadata not showing up in useUser() and getSession()

Ready to post? :mag: First, try searching for your answer.
Hey guys,

Using nextjs and auth0 js sdk’s.

We’ve successfully added app_metadata to our user using the management sdk here:

type Auth0UserMetadata = {
  organizationId?: string | null;
  role?: string | null;
};

const management = new ManagementClient({
  domain: env.AUTH0_DOMAIN_AND_REGION,
  clientId: env.AUTH0_CLIENT_ID,
  clientSecret: env.AUTH0_CLIENT_SECRET,
});

async function updateAuth0AppMetadata(userId: string, metadata: Auth0UserMetadata) {
  try {
    // const user = await management.updateAppMetadata({ id: userId }, metadata);
    const testGetUser = await management.users.get({ id: userId });
    console.log("testGetUser", testGetUser);
    const user = await management.users.update({ id: userId }, { app_metadata: metadata });

    

    console.log('User updated:', user);
    return user;
  } catch (error) {
    console.error("Error updating user in Auth0", error);
    throw error;
  }
}

For some reason, when we call getSession(), we do not see the app_metadata in the session.user object. How do we get this information to show up in all calls to getSession() and useUser()?

Hi @dev63,

Could you clarify if you are updating the user during an active user session? If so, you might need the user to reauthenticate or use silent authentication to see the updated data.

Additionally, you might need to create a post-login action script to append the app_metadata to either the access or ID token and then decode it to read that information.

Let me know if you have any questions.

Thanks,
Rueben

Hi Reuben,

Adding the post-login script worked mostly. Yes, we are trying to update an active session. user gets logged in, and then we update their metadata. Then, in other parts of the app, for example trpc context, getSession() is called to grab information. After handleCallback is called, we get or create a user in our db, and then we set the app_metadata to store further ids for the user, for example, RBAC settings.

export const GET = handleAuth({

  callback: async (req: NextRequest, ctx: { params: Record<string, string | string[]> }) => {
    try {
      const res = await handleCallback(req, ctx);
      console.log(">>> res in callback", res);

      const session = await getSession(req, res);
      if (!session) {
        console.error("No session found");
        return NextResponse.redirect(`${process.env.AUTH0_BASE_URL}/error`);
      }
      console.log(">>> session in callback", session.user.sub);

      const updatedSession = await handleGetOrCreateUser(session);
      console.log(">>> updated session after handling our ■■■■", updatedSession.user.sub);

      if (!updatedSession) {
        console.error("Session update failed");
        return NextResponse.redirect(`${process.env.AUTH0_BASE_URL}/error`);
      }

      let returnTo = `${process.env.AUTH0_BASE_URL}/dashboard/home`;

      // Create a new response with the redirect
      const redirectResponse = NextResponse.redirect(returnTo);

      // Copy all cookies from the original response to the new response
      res.headers.getSetCookie().forEach(cookie => {
        redirectResponse.headers.append('Set-Cookie', cookie);
      });

      // Add a flag to indicate that this is a post-login redirect
      redirectResponse.headers.set('X-Auth-Return-Redirect', '1');

      return redirectResponse;
    } catch (error) {
      console.error("Error in callback handler:", error);
      return NextResponse.redirect(`${process.env.AUTH0_BASE_URL}/error`);
    }
  },
});

exports.onExecutePostLogin = async (event, api) => {
  const userAppMetadata = event.user.app_metadata;
  api.accessToken.setCustomClaim("app_metadata", userAppMetadata)
  api.idToken.setCustomClaim("app_metadata", 
};

Thanks for your help.

1 Like

Can you elaborate on silent authentication?

1 Like

Hi @dev63,

Thanks for the responses.

Sure! Silent authentication is a process that re-authenticates the user without user interaction as long as there is an active session. To do so, you would include the prompt=none as an authorization parameter in your login request.

I recommend referring to our Configure Silent Authentication documentation for more information.

Thanks,
Rueben