Hi @alt.
Let me try to explain the behavior you are now seeing, the reasoning behind it, and the suggested workaround.
In the old days, when the OIDC specification was finalized, Auth0 would return the full user profile (what you describe in the first JSON) to applications requesting an authentication with the openid profile
scope. This included the identities
array, the full app_metadata
and user_metadata
objects, and every other property provided by the upstream identity provider. This is what we call the “Legacy User Profile”.
This is a potential security issue. While it might not look like so when you use just one first party web server application with “full powers”, the OIDC/OAuth2 model provides a model where you could have many different applications authenticating with your Auth0 domain, some with more access than other (including potentially third party applications not developed by you). Also, some applications could consume user information directly from the browser (where the information is less secure). For all these reasons, we want to limit the amount of information returned to applications by default, and that’s why we moved to full OIDC conformance.
The OIDC spec defines a series of scopes (profile
, email
and others) that let applications specify exactly what information they require from the user. Each scope represent a series of well defined properties (claims) that will be returned (see here for more information on the standard OIDC scopes and claims).
If you want to return additional claims as part of the authentication response (be it in the ID Token or from the /userinfo
endpoint) you can still do so, but you’ll need to be very explicit about it and write a rule that looks like this:
function(user, context, callback) {
// better to be explicit and
// only add custom claims for the specific application that requires them
// you can use context.clientID if it makes more sense to you
if (context.clientName !== "the_name_of_the_app") {
return callback(null, user, context);
]
// you will need to *namespace** the claims
// the URL doesn't have to be real, but can't be an Auth0 domain
const namespace = 'https://myapp.example.com/';
context.idToken[namespace + 'role'] = user.app_metadata.role;
context.idToken[namespace + 'preferred_contact'] = user.user_metadata.preferred_contact;
callback(null, user, context);
}
In the resulting user information payload, you’ll see the two claims added (with the respective namespace) that you can use directly in your application.
This is described in detail here: JSON Web Token Claims.
We understand that we are adding a little more friction with this, but the reasoning behind the decision is to avoid spilling out too much information by default and require developers to be more explicit when sending potentially sensitive information to applications. Hopefully this works out for you.