Auth0: how to include app_metadata in user info

Use Actions to get it all in a single request.

The process is actually very straightforward, but it comes with some gotchas that the auth0 docs don't tell you, or at least not in one go. It can be a pain to get it working, so here it is, with all the secrets!

1. Create an Action

By default, the Auth0 platform does not include app_metadata nor user_metadata with the user info.

Some posts out there will tell you to use the Management API to request that data separately, but then you'll end up making two API calls for what should be only one.

You can customize the login flow using Rules or the new Actions, which is now the preferred way.

Navigate to Auth0 Dashboard > Actions > Library, and select Build Custom. We'll name this action Add app_metadata to tokens. Click Create.

image.png

Replace whatever is in the code editor with the following:

/**
* Handler that will be called during the execution of a PostLogin flow.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'https://YOUR_DOMAIN_HERE';
  const { roles, permissions } = event.user.app_metadata;

  // Adds your data to the id token
  api.idToken.setCustomClaim(`${namespace}/roles`, roles);
  api.idToken.setCustomClaim(`${namespace}/permissions`, permissions);

  // Adds your data to the access token
  api.accessToken.setCustomClaim(`${namespace}/roles`, roles);
  api.accessToken.setCustomClaim(`${namespace}/permissions`, permissions);
};

Remember to replace the domain there with your own. The domain is used as a namespace for the claims you're adding, which is required by Auth0 and is also a best practice.

Also, you should add your information to either the id token or the access token, but not both. Choose one and delete the other.

Deploy your action.

2. Add your action to the login flow

Before your action can have any effect, you must include it in your login flow.

Navigate to Auth0 Dashboard > Actions > Flow and add it like this:

image.png

3. Test it

You can now login with a user to confirm that everything is working, but KNOW THIS: you must logout first, or remove your app from the list of authorized applications in the Users dashboard, otherwise you'll keep getting outdated info (without your newly included data):

image.png

With that out of the way, a call to the /userinfo endpoint should now include your data.

Get the auth code

https://YOUR_DOMAIN/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:3000&scope=openid%20profile

☝️ Replace YOUR_DOMAIN and YOUR_CLIENT_ID. Login if needed and grab the code in the URL after the redirect.

Exchange the code for a token

curl --request POST /
  --url https://YOUR_DOMAIN/oauth/token /
  --data "grant_type=authorization_code&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&redirect_uri=http://localhost:3000&code=THE_CODE"

☝️ Again, replace with your variables. Grab the auth token.

Get the user info, now with your data

curl --url https://YOUR_DOMAIN/userinfo /
  -H "Authorization: Bearer THE_AUTH_CODE"

☝️ The response should include your data.


This process is derived from what you can find in the docs: Simple Use Cases: Scopes and Claims, section Add custom claims to a token.