Auth0 Home Blog Docs

Best practices for custom claims using OIDC-conformant Auth0.js

auth0js

#1

I’m using Auth0.js (^9.6.0) in a Vue app (^2.5.16) and using the OIDC-conformant version of webAuth.authorize() to authenticate users. Since the default profile returned by webAuth.client.userInfo() doesn’t include user_metadata or app_metadata, I followed the docs on creating custom claims and created a rule like this one:

function (user, context, callback) {
  const ns = "https://example.com/";
  context.idToken[ns + 'user'] = user;
  callback(null, user, context);
}

Then I initialize webAuth including the custom namespaced claim to my scope as follows:

const webAuth = new auth0.WebAuth({
  domain: "example.auth0.com",
  clientID: "[MY-CLIENT-ID]",
  scope: "openid https://example.com/user"
});

As expected, when I call webAuth.client.userInfo(), the API returns the full user object under my custom namespaced claim. It contains user_metadata and app_metadata just like I want.

My Question

Is there anything wrong/dangerous/inefficient/ill-advised with getting the user profile this way? I haven’t seen any documentation or tutorials that suggest doing it this way, which makes me wonder if maybe there’s a good reason NOT to do it. I just want to make sure I’m using best practices, and I’m still relatively inexperienced using Auth0.

Thanks!!!


#2

I don’t think it’s fully wrong, but it’s definitely not a best practice.

  1. For starters, you’re completely throwing out a couple of OIDC features. For instance, you’re giving up the normalized user profile Auth0 provides, which you would get if you were to use scopes like email, profile, address and phone.

  2. There’s also the issue of oversharing: do you really want the user (because they’re capable of viewing and decoding the ID token) to see literally everything in their profile?

  3. You run into the risk of making your token too big. The token is sent back to your app as a URL hash and that means you can run into the maximum URL length. You wouldn’t be the first: The generated token is too large

So, I’d say for those three reasons (not in the spirit of OIDC, oversharing and risk of an oversized token), I wouldn’t advice it. But again… it’s a bit of a grey area.

Anyone else with more experience (or, fingers crossed, an Auth0 employee) who can help out here?


#3

@thijmen96,

Thank you for your response! This is exactly the kind of discussion I was hoping to start in this thread.

As a result of your comment, I discovered the full list of standard OIDC claims with descriptions of what each element is designed to provide. Because I spent most of my time looking at the Auth0.js reference, I somehow missed these key resources:

As such, I was unaware that other standard claims existed beyond openid, profile, email, and offline_access. My bad for not fully RTM!

That being said, I’ve found it exceedingly difficult to figure out how to do what I expect to be SIMPLE things, such as:

  • Add/Edit the family_name or given_name of a user profile!
  • Edit the name property of the user. OIDC indicates this should be the full name, but Auth0 defaults this property to the email address and doesn’t appear to allow changes
  • Edit the nickname
  • Add other (supposedly) basic properties like phone and address

It is NOT clear from any documentation that I’ve read where these values should even be stored. Likely candidates appear to be:

  • Direct properties of the base user object: see Auth0 example and OIDC example
    The problem with this approach is that unless the identity is pulled in from a 3rd party idP (e.g. Google), there doesn’t seem to be any way to edit the base user object, at least not using Auth0.js. There’s not even a way to add these properties manually via the Auth0 admin dashboard.
  • Added onto user_metadata
    The problem with this approach is that these values are not automatically merged into the user profile, even when the profile claim is passed in the scope. I tried adding user.user_metadata.family_name and user.user_metadata.given_name to a profile hoping that I’d be able to retrieve them with a basic webAuth.authorize() call, but no such luck.
  • Added onto user_profile
    There’s a vague, one-time reference to a user_profile property in the docs but I’m not sure that this really even exists. There’s no information about how to update it or what it should be used for.

I guess what frustrates me is that the workflow for getting a person fully logged in seems to require so many steps. I have a vague feeling that what I want to do is described somewhere in the documentation, but not all in one place. The Quickstart seems to advocate using Auth0.js but the more I get into it, it seems it might have been simpler just to work directly with the raw REST API.

So, I guess the reason that I created a custom claim that returns the entire user object was that it seemed too cumbersome to make 3+ API calls just to get all of the basic profile information. Perhaps the answer is just to create a user_metadata.profile property or something that I put a limited amount of information in, but then retrieve upon authorization.