Nextjs-auth0: Fetch user_metadata

Created on 22 Nov 2019  路  19Comments  路  Source: auth0/nextjs-auth0

It is possible to fetch (using handleProfile()) user_metadata from account of the user?

guidance

All 19 comments

I'm also interested in doing this. @jurajkrivda did you find a workaround?

Hi everyone,

Take a look here . I think this issue is outside the scope of this module

Thanks @HelloEdit - a helpful article. I'm struggling to know how/where to implement the non standard claim in the authentication flow with this SDK.

From the article, We can, however, define a non-standard claim by namespacing it through a rule: is followed by a JS code snippet. I'm not clear if this defining of a non-standard claim is in my application code or somewhere in the Auth0 interface.

Do you have more clues?

For anyone else finding this, what we're looking for are 'Rules' in the Auth0 Dashboard which can be used to add the metadata as a non-standard claim to the returned OIDC object.

https://auth0.com/docs/rules/guides/metadata

Can you share the Rule that you added to enrich the response with metadata?

function (user, context, callback) {
  user.user_metadata = user.user_metadata || {};
  user.user_metadata.full_name = user.user_metadata.full_name || user.name;
  context.idToken['http://full_name'] = user.user_metadata.full_name;

  auth0.users.updateUserMetadata(user.user_id, user.user_metadata)
    .then(function(){
        callback(null, user, context);
    })
    .catch(function(err){
        callback(err);
    });
}

It will only send back things that look like they've been namespaced - hence the weird http:// bit. I then tidy that up on the client side.

I am looking for getting the metadata info as well. Anyone were able to get this working?

was anyone able to find a solution?

^ Would be great to find a solution

I was making a separate call on server-side using the 'sub' field of the logged in user to get the full user information

I was making a separate call on server-side using the 'sub' field of the logged in user to get the full user information

Would you mind sending a code snippet?

Like the following

const body = JSON.stringify({
      'client_id': process.env.AUTH0_CLIENT_ID,
      'client_secret': process.env.AUTH0_CLIENT_SECRET,
      'audience': process.env.AUTH0_ADMIN_AUDIENCE,
      'grant_type': 'client_credentials'
    });

    const token = await fetch('https://' + process.env.AUTH0_DOMAIN + '/oauth/token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: body
    }).then(function (a) {
      return a.json();
    }).then((json) => {
      return json;
    });

    const full_user = await fetch('https://' + process.env.AUTH0_DOMAIN + '/api/v2/users/' + user_id, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        'authorization': 'Bearer ' + token.access_token
      }
    }).then(function (a) {
      return a.json();
    }).then((json) => {
      return (json);
    });

How do we refresh this data once it changes? If that data is updated from the Auth0 dashboard, I can't seem to fetch the new data without logging out and logging back in again.

Would be great to find a solution to this

How do we refresh this data once it changes? If that data is updated from the Auth0 dashboard, I can't seem to fetch the new data without logging out and logging back in again.

was able to access like this

const { ManagementClient } = require('auth0');
const authUtil = new ManagementClient({
  domain: process.env.AUTH0_DOMAIN,
  clientId: process.env.AUTH0_CLIENT_ID,
  clientSecret: process.env.AUTH0_CLIENT_SECRET,
  scope: 'read:users update:users read:users_app_metadata',
});
// where userId is authUser.sub
const userObjectWithMetadata = await authUtil.getUser({ id: userId });

Hi, you need to use a Rule to add the metadata to the ID Token. Then it will be available in the user profile.
Check out the following docs page to learn more: https://auth0.com/docs/rules/metadata

function(user, context, callback) {
context.idToken['http://user_metadata'] = user.user_metadata;
callback(null, user, context);
}

This feels so wrong. But it works........ Shouldn't this be baked into the framework so we can easily add custom fields to users?

Hi @LeakedDave

The ID Token is signed by the Authorization Server, so any modifications to it will have to happen there.

Once the token is decoded on the client, we persist a user object that you can add fields to, see the afterCallback example for more info

Got it.

This is how I have it setup now, if anyone else has trouble. It merges all user_metadata into the user object.

Add User Metadata Rule

function(user, context, callback) {
  context.idToken['https://www.yourdomain.com/user_metadata'] = user.user_metadata;
  callback(null, user, context);
}

/src/pages/api/auth/[...auth0].js

import { handleAuth, handleCallback, handleLogout } from '@auth0/nextjs-auth0'

const afterCallback = (req, res, session, state) => {
  session.user = { ...session.user, ...session.user['https://www.yourdomain.com/user_metadata'] }
  delete session.user['https://www.yourdomain.com/user_metadata']

  return session
}


export default handleAuth({
  async logout(req, res) {
    try {
      await handleLogout(req, res, { returnTo: "/dashboard" })
    } catch (error) {
      res.status(error.status || 500).end(error.message)
    }
  },
  async callback(req, res) {
    try {
      await handleCallback(req, res, { afterCallback })
    } catch (error) {
      res.status(error.status || 500).end(error.message)
    }
  }
})
Was this page helpful?
0 / 5 - 0 ratings

Related issues

shicholas picture shicholas  路  5Comments

RyGuyM picture RyGuyM  路  5Comments

davemaier picture davemaier  路  4Comments

platocrat picture platocrat  路  3Comments

lunchboxav picture lunchboxav  路  5Comments